2015-11-08 1 views
0

Я работаю над созданием двоичного дерева поиска с использованием классов типа интерфейса, которые мне были предоставлены. У меня есть класс BSTInterface, который состоит из чистых виртуальных функций. Он унаследован BST.h, который реализуется BST.cpp. BSTInterface выполняет функцию, называемую getRootNode(), которая возвращает NodeInterface * My NodeInterface.h - класс, состоящий из чистых виртуальных функций, которые унаследованы от Node.h, который реализован Node.cpp. В моей функции BST :: getRootNode() я могу вернуть узел *, или мне нужно вернуть NodeInterface *? Если мне нужно вернуть NodeInterface *, могу ли я просто установить NodeInterface * = Node *? Любая помощь, понимающая взаимосвязь между родительским и дочерним объектами, будет с благодарностью оценена. Спасибо огромное!Может ли указатели на дочерние объекты обрабатываться как указатели на родительские объекты?

+0

Вы можете вернуть указатель на производный класс в качестве указателя на базовый класс. Это основа полиморфизма. –

ответ

1

В частности, для вашего случая, C++ допускает covariant return types. Это означает, что вы не можете вернуть только производный типа класса из унаследованного метода, но вы можете также объявить унаследованную функцию, чтобы вернуть devired типа:

class Node {}; 
class SpecialNode : public Node {}; 

class Base { 
public: 
    virtual Node* getRootNode() = 0; 
}; 

class Derived : public Base { 
public: 
    virtual SpecialNode* getRootNode() override { 
     /* return a special node... */ 
    } 
}; 

В общем, вы можете присвоить указатель производного типа, указатель базового типа:

Node* node = new SpecialNode(); 

Обратите внимание, что это относится только к ссылкам и указателям. Вы не можете сделать то же самое с объектами, которые не объявлены как указатели или ссылки:

void someFunction (Node node) {} 

SpecialNode sn; 

// Causes "slicing" to occur 
someFunction(sn); 

Нарезка происходит при достаточно памяти выделяется только для базового класса, так как компилятор использует информацию о типе параметра узла через параметр (компилятор выделяет достаточно памяти только для Node, а не SpecialNode). Если были объявлены следующие

class Node { 
private: 
    int x; 
}; 

class SpecialNode : public Node { 
private: 
    int y; 
}; 

элемент данных «у» не будет присутствовать в узле передается someFunction, так как он был «нарезанный». Обратите внимание, что это происходит только в прохождении по параметрам значения, а не по ссылке или по указателю. Для получения дополнительной информации см. object slicing.

+0

Это очень полезно! огромное спасибо. –

+0

Рад помочь. В качестве побочного примечания ссылки и указатели работают, потому что размер указателя (и ссылки, обычно реализованной с использованием указателя компилятором) всегда одинакового размера на той же машине. Поэтому указатель на базовый тип имеет тот же размер, что и указатель на производный тип. То же самое нельзя сказать о базовом и производном объекте: базовый объект имеет одно целое (x), а производный объект имеет два целых числа (x и y). Это основная причина, по которой указатели и ссылки не подвергаются обработке объектов. –