Проблема наследования при переносе (наследовании) из библиотеки C ++ - PullRequest
2 голосов
/ 10 июня 2009

Библиотека, которую я использую, имеет класс G и класс S, который наследует G.

Мне нужно было добавить к ним функциональность, поэтому я обернул G и S, скорее, я унаследовал от них создание Gnew и Snew соответственно.

Итак, мое наследство:

   
 G --> Gnew  
 |      
 v    
 S --> Snew  

Но я хочу использовать Gnew в Snew, и когда я пытаюсь включить заголовок Gnew (в файле реализации Snew), чтобы использовать его ... охранники включения маскируют определение Gnew в Snew ???

Как я могу использовать Gnew в Snew? Прямо сейчас, компилятор даже не позволяет мне объявлять Gnew в файле определения Snew (что для меня не имеет смысла), если я не пересылаю объявление внутри класса.

В Snew (если я пересылаю объявление до определения Snew), у меня есть:

...
Gnew *g;

Ошибка:

error: ISO C++ forbids declaration of ‘Gnew’ with no type

Если я поменяю Snew на:

...
class Gnew *g;
Gnew *g;

Ошибка:

error: invalid use of undefined type ‘struct Snew::Gnew’

Примечание: Я пытался абстрагироваться от проблемы, поэтому я закрываю это и снова открываю лучшую формулировку вопроса ...

Ответы [ 4 ]

2 голосов
/ 10 июня 2009

Не включайте заголовочные файлы в заголовочные файлы, когда они не нужны. Просто объявите тип, который вы хотите использовать, и включите заголовочный файл в .cpp файл, который должен знать о реализации этого типа (в данном случае Gnew) Заголовочный файл не нуждается в этой информации.

// snew.h

// forward declare Gnew
class Gnew;

class Snew : public S
{
    Gnew* gnew;
};

// snew.cpp

#include "gnew.h"

// ..

Не вижу смысла в использовании множественного и виртуального наследования. Сначала у вас есть нормальная простая цепочка наследования, подобная этой: G -> S -> Snew. И вы хотите использовать Gnew в S, но вы отправляете G в конструктор S и делаете dynamic_cast для Gnew. Почему бы вам просто не отправить Gnew прямо в конструктор S? Как это:

SteadyStateDBGA(const Genome& g, const std::string& rootD, 
                const std::string& parName);
2 голосов
/ 10 июня 2009

Это совершенно законный случай для виртуального наследования . Что касается ошибок компиляции - убедитесь, что эти защитные элементы различны во всех четырех заголовках.

Отвечая на ваш комментарий: вам нужно, чтобы оба класса были выведены практически. Это должно быть что-то вроде следующего:


class G {};
class S: public virtual G {};
class Gnew: public virtual G {};
class Snew: public S, public Gnew {};

Таким образом, Snew имеет только один недвусмысленный подобъект class G. Я не знаю, если вы контролируете источник для class S, так что это может не сработать для вас.

В любом случае - наследование переоценено ;)

1 голос
/ 10 июня 2009

Звучит так, будто ваши охранники так или иначе сломаны. Если срабатывает защита включения, то это должно означать, что код уже включен в модуль компиляции. Можете ли вы указать точную ошибку, которую вы получаете?

1 голос
/ 10 июня 2009

Где цикл? И зачем Gnew включать заголовок Snew?

[Изменить] Хорошо, я думаю, что ваши стрелки наследования противоположны тому, что принято. Но это должно помочь вам разобраться:

В Gnew.h:

#pragma once
#if !defined(Gnew_h)
#define Gnew_h

#include "G.h"

class Gnew : public virtual G
{
  // added functionality here.
};

#endif // Gnew_h

В Snew.h:

#pragma once
#if !defined(Snew_h)
#define Snew_h

#include "S.h"
#include "Gnew.h"

class Snew : public virtual Gnew, public virtual S
{
  // added functionality here.
};

#endif // Snew_h

Вы не должны отправлять декларировать что-либо.

Обратите внимание, что это работает, как и ожидалось, только если S наследует виртуально от G. Если все эти проблемы множественного наследования являются слишком большими проблемами, вам, вероятно, следует просто адаптировать библиотечные классы вместо того, чтобы наследовать от них. 1015 *

Помогает ли это?

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