C ++: построить подкласс из экземпляра базового класса? - PullRequest
1 голос
/ 26 июня 2010

У меня есть три структуры, одна из которых наследует от двух других:

typedef struct _abc
{
    int A;
    int B; 
    int C;
} ABC;

typedef struct _def
{
    int D;
    int E;
    int F;
} DEF;

typedef struct _abcdef : ABC, DEF { } ABCDEF;

(я хочу, чтобы третья структура содержала все члены первых двух. Есть ли лучший способ сделать это?)

Теперь у меня есть полностью заполненные экземпляры ABC и DEF, и я хочу создать новый ABCDEF экземпляр:

int main()
{
    ABC abc;
    abc.B = 2;
    abc.C = 1;
    abc.A = 10;

    DEF def;
    def.D = 32;
    def.E = 31;
    def.F = 90;

    // make a new ABCDEF with all the values of abc and def
}

Как лучше всегосоздать ABCDEF?Я мог бы сделать это, но это отчасти отстой:

ABCDEF abcdef;
abcdef.A = abc.A;
abcdef.B = abc.B;
abcdef.C = abc.C;
abcdef.D = def.D;
abcdef.E = def.E;
abcdef.F = def.F;

Вышеприведенное связано с членами структур и является грязным, если добавлено много членов.

Ответы [ 3 ]

8 голосов
/ 26 июня 2010

Это C ++. Эти typedef не нужны. И у вас есть конструкторы:

struct abc {
    int A;
    int B; 
    int C;
    abc(int a, int b, int c) : A(a), B(b), C(c) {}
};

struct def {
    int D;
    int E;
    int F;
    def(int d, int e, int f) : D(d), E(e), F(f) {}
};

struct abcdef : abc, def {
  abcdef(const abc& a, const def& d) : abc(a), def(d) {}
};

int main()
{
   abc a(2,1,10);
   def d(32,31,90);
   abcdef ad(a,d);

   return 0;
}
4 голосов
/ 26 июня 2010

Я хочу, чтобы третья структура содержала всех членов первых двух. Есть ли лучший способ сделать это?

Возможно ли, чтобы ваша третья структура содержала экземпляры двух других? (Также может быть более логичным, если это отношение «есть» вместо «есть».)

struct ABCDEF
{
    ABC abc;
    DEF def;
};

Конечно, это меняет то, как вы обращаетесь к этим членам и используете их. Однако, если это возможно для вас, это открывает несколько простых способов инициализации ABCDEF.

ABC abc = { 10, 2, 1 };
DEF def = { 32, 31, 90 };

// Assign members from preexisting variables.
ABCDEF abcdef1;
abcdef1.abc = abc;
abcdef1.def = def;

// Initialize aggregate using preexisting variables.
ABCDEF abcdef2 = { abc, def };

// Initialize the entire aggregate in one statement.
ABCDEF abcdef3 = { 10, 2, 1, 32, 31, 90 };

В противном случае, если вам нужно, чтобы ABCDEF наследовал от двух других, я бы обычно рекомендовал концепцию из ответа sbi, где вы бы добавили соответствующие конструкторы. Хотя в зависимости от ваших конкретных потребностей, возможно, можно будет немного упростить его, используя агрегатную инициализацию и конструкторы сгенерированных копий.

struct ABC
{
    int A;
    int B;
    int C;
};

struct DEF
{
    int D;
    int E;
    int F;
};

struct ABCDEF : public ABC, public DEF
{
    ABCDEF(const ABC& abc, const DEF& def) : ABC(abc), DEF(def) {}
};

int main()
{
    ABC abc = { 10, 2, 1 };
    DEF def = { 32, 31, 90 };
    ABCDEF abcdef(abc, def);

    return 0;
}
0 голосов
/ 26 июня 2010

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

Затем, существует уродливый трюк (не рекомендуется, но выполнимо) с использованием приведений, чтобы использовать сгенерированные компилятором операторы присваивания:

ABC abc = { 1, 2, 3 };
DEF def = { 4, 5, 6 };
ABCDEF o = {};
static_cast<ABC&>(o) = abc;
static_cast<DEF&>(o) = def;

И это действительно, действительно, действительно ужасный ответ. Просто написал это, чтобы указать, что означает static_cast -приведение производного объекта к базовому классу: он генерирует ссылку на тип base, которая ссылается на часть подобъекта этой базы, включая смещение, необходимое, когда в игру вступает множественное наследование. Обратите внимание, что если бы вместо этого использовалось reinterpret_cast, оба назначения перезаписывали бы подобъект ABC экземпляра ABCDEF.

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