У меня есть следующий код:
main.hxx:
#include <iostream>
class Base{
public:
Base() {}
~Base() {}
virtual void whoAreYou() { std::cout << "I am base!" << std::endl;}
};
class Sub : public Base{
public:
Sub() {}
~Sub() {}
virtual void whoAreYou() { std::cout << "I am Sub!" << std::endl;}
};
class Factory {
public:
static Base getBase() { return Base(); }
static Base* getBasePtr() { return new Base(); }
static Base getSub() { return Sub(); }
static Base* getSubPtr() { return new Sub(); }
};
main.cxx
#include "main.hxx"
int main (int argc, char **argv) {
// Non pointers
Factory::getBase().whoAreYou();
Factory::getSub().whoAreYou();
// Pointers
Base* basePtr = Factory::getBasePtr();
Base* subPtr = Factory::getSubPtr();
basePtr->whoAreYou();
subPtr->whoAreYou();
delete basePtr, subPtr;
return 0;
}
При запуске он печатает следующее:
I am base!
I am base!
I am base!
I am Sub!
Я ожидал "Factory :: getSub(). WhoAreYou();" напечатать "Я Суб!". Это потому, что, когда не используется указатель, он попадает на базу?
Я ожидал
Factory::getSub().whoAreYou();
напечатать "Я Суб!".
Нет, функция возвращает Base
, поэтому Base
- это то, что вы получаете.
Это потому, что, когда не используется указатель, он попадает на базу?
Да (хотя слово "преобразуется" не "casted" - литье - это явное преобразование, и это преобразование неявно). Это иногда называют "срезанием", так как часть производного класса объекта "разрезается" при копировании.
Кроме того, будьте осторожны:
delete basePtr, subPtr;
только удаляет subPtr
. Для каждого из них требуется отдельное выражение. Вам также нужен виртуальный деструктор в Base
чтобы безопасно удалить subPtr
.
Эта строка создает Sub
затем вызывает Base
конструктор копии по умолчанию для создания экземпляра Base
из экземпляра Sub
:
static Base getSub() { return Sub(); }
Следовательно, ваш журнал.
Более Generaly Base
является Base
экземпляром, тогда как Base*
представляет собой указатель на Base
экземпляра или объект, который наследует Base
.