Как проверить, определен ли абстрактный метод C ++ во время выполнения - PullRequest
3 голосов
/ 30 ноября 2010

Как проверить, определен ли абстрактный метод C ++ во время выполнения

class ABase{
public:
 virtual void do1() = 0;
};

class BBase: public ABase{
public:
 virtual void do1(){}
};

class CBase: public ABase{
public:
};

ABase * base = rand() % 2 ? new BBase() : new CBase();
if(&(base->do1) != 0)
  base->do1();

Это дает ошибку.

Спасибо, Макс

Ответы [ 7 ]

14 голосов
/ 30 ноября 2010

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

4 голосов
/ 30 ноября 2010

Для создания экземпляра класса должен быть реализован абстрактный метод.Нет такой вещи как проверка, реализован ли метод, компилятор сделает это за вас.В этом случае у вас не может быть объекта CBase, потому что он имеет абстрактные методы.

3 голосов
/ 30 ноября 2010

Компилятор не позволит вам создать экземпляр типа, который не определяет все абстрактные методы. В приведенном выше примере вызов new CBase () сгенерирует ошибку во время компиляции по принципу «не удается создать экземпляр абстрактного типа».

3 голосов
/ 30 ноября 2010

CBase является абстрактным, потому что он не переопределяет ABase :: do1 ().Следовательно, вы не можете создать его экземпляр.Или, скорее, это то, что произошло бы, если бы вы объявили do1 () как виртуальный.Но сейчас он просто не скомпилируется.

Хотелось бы знать, зачем вы это делаете.

1 голос
/ 30 ноября 2010

Предполагая, что вы не забыли сделать do1 () виртуальным, вы можете проверить & ABase :: do1, & BBase :: do1 и & CBase :: do1 во время выполнения. Я не уверен, что сравнение & ABase :: do1 и & CBase :: do1 вернет одно и то же значение только потому, что CBase не переопределяет функцию, и только потому, что это происходит в одной системе, означает, что всегда будет.

Хотя вы можете проверить их во время выполнения, вы не сможете использовать эту информацию для создания объекта класса CBase, если он не является абстрактным, поскольку он не сможет скомпилироваться, когда он есть.

Вместо этого вы могли бы сделать это способом «C»: иметь таблицу указателей на функции, которые могут иметь значение NULL, проверить, является ли один из них NULL, и создать структуру такого экземпляра или вызвать его, если это не так. .

1 голос
/ 30 ноября 2010

Вы не можете создать экземпляр CBase, так как он ... абстрактный, то есть не реализует все чисто виртуальные функции своих родителей.

Возможно, проще всего определить реализацию заглушки в ABase:

class ABase {
public:
 void do1() { /* do nothing */ }
};

class BBase: public ABase {
public:
 void do1() { /* do something */ }
};

class CBase: public ABase {};

ABase * base = rand() % 2 ? new BBase() : new CBase();
base->do1();
1 голос
/ 30 ноября 2010

Вам не нужно проверять, реализован ли метод во время выполнения (в любом случае вы не можете в этом случае), потому что CBase должен реализовать do1 () для удовлетворения наследования от ABase.

...