2013-11-09 5 views
-1

У меня есть 2 классов:указатель на абстрактный базовый класс нужно бросить? C++

class MyAbstractClass 
{ 
public: 
virtual const std::string& getStr() const =0; 
} 

class MyRealClass : public MyAbstractClass 
{ 
public: 
virtual const std::string& getStr() const { return m_str;}; 

private: 
std::string m_str; 
} 

Я имею в основной:

MyAbstractClass* ptr = new(MyRealClass("some string")); 

Я хочу, чтобы получить информацию, хранящуюся в строку MyRealClassчерез указатель на базовый класс. Нужно ли мне как-то отличить ptr до MyRealClass, чтобы получить информацию? или среда выполнения будет достаточно умна, чтобы понять, что я на самом деле звоню getStr от MyRealClass?

ptr->getStr(); или еще что-то вроде static_cast<MyRealClass*>(ptr)->getStr(); или даже dynamic_cast<MyRealClass*>(ptr)->getStr();?

В общем, действительно ли нам нужно использовать, если мы используем указатель на базовый класс Abstract, а не только на простой (реальный) базовый класс?

+0

Вы пробовали какие-либо из этих альтернатив? Была ли какая-нибудь работа? Неужели это случилось? –

+0

Пожалуйста, скомпилируйте свой код перед запросом! –

+0

Обратите внимание, что вы можете удалить половину круглых скобок в инструкции 'new', и это будет означать одно и то же. –

ответ

2

То, что вы хотите, называется Полиморфизм, это особенность объектно-ориентированных языков программирования (таких как C++).

Чтобы сделать метод полиморфным, вы должны пометить его как виртуальный (как в примере с getStr()), если ваши методы являются виртуальными, вы можете переопределить их в производном классе, и если вы вызываете их метод из указателя базового класса будет вызывать версию созданного вами класса (MyRealClass в вашем примере). Если вы не пометите их как виртуальные, они вызовут версию метода из типа указателя, который у вас есть. (Если вы хотите знать больше об этой теме, поиск «Виртуального стола», «виртуальной отправке» и «позднего связывания»)

Обратите внимание, что когда вы пишете:

virtual void someMethod() = 0; 

Вы объявляете, что известно как чистый виртуальный метод, поскольку у них нет собственной реализации, вы вынуждены определять их в производных классах (то есть как интерфейсы и абстрактные классы создаются на C++).

0

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

MyAbstractClass* ptr = new(MyRealClass("some string")); 

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


Если вы хотите отличить из базы в производную - static_cast недостаточно. Затем вам нужно использовать dynamic_cast и проверить, выполнено ли это.

0

Нет; вы можете вызвать членов указателей на детей абстрактных базовых классов через абстрактные классы. Хотя приведенный вами пример кода является неполным.

Добавление виртуального деструктора к интерфейсу, и конструктору для конкретного класса, а также очистки некоторых точек с запятой - мы получаем:

#include<string> 

class MyAbstractClass{ 
public: 
    virtual const std::string& getStr() const = 0; 

    virtual ~MyAbstractClass(){} 
}; 

class MyRealClass : public MyAbstractClass{ 
public: 
    MyRealClass(std::string str) : 
    m_str(str) 
    {} 

    virtual const std::string& getStr() const{ 
    return m_str; 
    } 
private: 
    std::string m_str; 
}; 

Теперь, вызов MyAbstractClass* ptr = new MyRealClass("some string"); позволит ptr->getStr() возвращения «некоторому строка».

Смежные вопросы