использование переменных для определения типа класса или пространства имен - PullRequest
1 голос
/ 07 июля 2010

Хорошо, поэтому у меня появилась блестящая идея использовать пространства имен и оператор if для изменения результата переменных, в PHP я представляю, что мог бы использовать конкатенацию, однако, похоже, что до сих пор в c ++ нет конкатенации.,

так есть ли способ заставить этот код работать?

namespace Blue
{

int seven = 7;
int eight = 8;


}

namespace Red
{

int seven = 1;
int eight = 2;

}

и вот основной файл cpp

int choice;

cin >> choice;

if(choice == 1)
{
    char A[] = "Blue";

}else if(choice == 2){

    char A[] = "Red";

}

cout << A::seven << endl;

cout << A::eight << endl;

Ответы [ 7 ]

8 голосов
/ 07 июля 2010

Вы не можете решить, какое пространство имен использовать во время выполнения.

Это только во время компиляции.

2 голосов
/ 07 июля 2010

Я не думаю, что есть способ сделать это, и если бы это было, это, вероятно, плохая идея.Обычно вы выполняете это поведение в C ++, используя полиморфизм, например:

class Color {
  virtual int seven() = 0;
  virtual int eight() = 0;
};
class Blue : public Color {
  int seven() { return 7; }
  int eight() { return 8; }
};
class Red : public Color {
  int seven() { return 1; }
  int eight() { return 2; }
};

и затем:

int choice;
Color* color;

cin << choice;
if (choice == 1)
  color = new Blue;
else
  color = new Red;

cout << color->seven() << endl;
cout << color->eight() << endl;

delete color;
2 голосов
/ 07 июля 2010

Нет, это не сработает, потому что пространство имен вычисляется во время компиляции, а содержимое A неизвестно до времени выполнения. Я часто сталкиваюсь с этими проектами. Один из языков, с которыми я взаимодействую, имеет динамическую типизацию, известную во время выполнения, и C ++ использует разрешение времени компиляции для набора. Обычно вы обходите это с помощью оператора case, который вызывает специализированные шаблонные функции.

    enum Choice
    {
        blue,
        red
    }

    template <Choice c>
    struct Option
    {
        enum {seven=0};
        enum {eight=0};
    };

    template <>
    struct Option<blue>
    {
        enum {seven=7};
        enum {eight=8};
    }

    template <>
    struct Option<red>
    {
        enum {seven=1};
        enum {eight=2};
    }

    ...

    switch (choice)
    {
    case red:
        cout << Option<red>::seven << endl;
        cout << Option<red>::eight << endl;
    case blue:
        cout << Option<blue>::seven << endl;
        cout << Option<blue>::eight << endl;
    }

обратите внимание, что вы не можете сделать что-то вроде

cout << Option<choice>::seven << endl

потому что значение выбора не известно во время компиляции.

Они мне так нравятся: все, что находится в шаблонном аргументе, должно быть известно во время компиляции, все, что известно только во время выполнения, должно быть включено в оператор case, который затем вызывает правильно шаблонную функцию.

Обратите внимание, что это очень сложный способ изменения значений 7 и 8, который можно сделать проще другим способом (скажем, картой), но есть случаи, когда это очень полезно. Я делаю это все время.

2 голосов
/ 07 июля 2010

Невозможно назначить классы или пространства имен и сделать так, чтобы результат namelookup зависел от этого. Но вы можете назначить адрес переменных. Так что в вашем примере вы могли бы сказать

array<int*, 2> nums;    
if(choice == 1)
{
    array<int*, 2> blues = {{ &Blue::seven, &Blue::eight }};
    nums = blues;
} else if(choice == 2) {
    array<int*, 2> reds = {{ &Red::seven, &Red::eight }};
    nums = reds;
}

cout << *nums[0] << endl;
cout << *nums[1] << endl;

Однако в этом случае вы можете поместить отпечаток в каждое соответствующее предложение if, что мне кажется более легким

if(choice == 1)
{
    cout << Blue::seven << endl;
    cout << Blue::eight << endl;
} else if(choice == 2) {
    cout << Red::seven << endl;
    cout << Red::eight << endl;
}

Если вы осуществляете доступ часто, вы можете поместить цвета в единую структуру данных

typedef std::array<int, NumberCount> number_array;
typedef std::array<number_array, ColorCount> color_array;

color_array colors = {{ {{ 7, 8 }}, {{ 1, 2 }} }};

Таким образом, вы можете использовать индекс, возможно, использовать перечисления для названий цветов вместо необработанных чисел

int arrayIndex = -1;
if(choice == 1)
{
    arrayIndex = 0;
} else if(choice == 2) {
    arrayIndex = 1;
}

if(arrayIndex != -1) {
    cout << colors[arrayIndex][0] << endl;
    cout << colors[arrayIndex][1] << endl;
}

Таким образом, вы также можете перебирать цвета (используя функцию size() массива или его интерфейс итератора). array является частью TR1, C ++ 0x и Boost.

1 голос
/ 07 июля 2010

Мне кажется, что вас не очень волнует вопрос, который вы задаете, но вы действительно хотите знать: «Какой смысл в пространствах имен?»

Пространства имен используются главным образом для разделения классов (и другихэлементы данных), которые имеют одинаковые имена друг от друга.

Еще до стандартизации C ++ не было std :: string, но каждая сторонняя библиотека имела свое собственное.Итак, если вы хотите использовать библиотеку Widgetworks для некоторых вещей и библиотеку CoolObjects для других вещей, у вас возникнет проблема, если вы просто напишите:

#include "widgetworx.h"
#include "coolobjects.h"

Поскольку оба будут определять класс с именем string,Таким образом, комитет по стандартизации понял, что если бы они добавили свои string, теперь у вас их будет три.Там решением были пространства имен.Стандартный строковый класс (и все другие стандартные классы) будет находиться в пространстве имен std, и он будет использоваться только тем, кого вы специально указали, чтобы использовать его.Кроме того, вы можете вручную обернуть старые файлы заголовков в пространства имен, чтобы разделить их:

namespace WW
{
    #include "widgetworx.h"
}
namespace CO
{
    #include "coolobjects.h"
}

, а затем просто использовать нужный фрагмент:

using CO::matrix;
using WW::complex;
using std::string;
1 голос
/ 07 июля 2010

Вы не можете сделать это в C ++ напрямую.Однако вы можете использовать std :: map для достижения аналогичного результата:

std::map<std::string, int> Blue;
Blue["seven"] = 7;
Blue["eight"] = 8;
assert(Blue["seven"] == 7);
1 голос
/ 07 июля 2010

Это не решает проблему пространства имен, но поскольку вы упомянули конкатенацию строк ...

Чтобы объединить строки в C ++:

string a = "Hello, ";
string b = "World!";
string c = a + b;

I 'Я не совсем уверен, что вы подразумеваете под кодом в вашем вопросе не работает.Вы выводите две строки в отдельных строках (endl эквивалентно "\n" + очистка потока).

Edit

Я думаю, что проблема в том, что вы пытаетесьиспользовать массивы символовХотя это технически строки, они не являются способом C ++ для создания строк.Если вы хотите создавать такие строки, как C, используйте стандартную библиотеку C strcat (или, предпочтительно, более безопасные версии, которые, вероятно, поставляются с вашим компилятором).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...