前言
当函数返回一个派生类对象的指针(或智能指针)时,这个返回类型可以是基类的指针(或智能指针)。这种特性基于C++的多态性,允许基类指针指向派生类对象。这是面向对象编程中的一个核心概念,使得代码可以更加通用和灵活。
多态性和返回类型
多态性允许我们通过基类的指针(或引用)来操作不同的派生类对象,而不需要知道具体的派生类是什么。这意味着,函数可以返回基类类型的指针或智能指针,实际上指向的是派生类的实例。这种做法有几个重要的好处:
- 封装:隐藏了具体实现的细节,只暴露了基类定义的接口。这样,实现细节的改变不会影响到使用这些对象的代码。
- 可替换性:可以在不改变外部代码的情况下,更换对象的具体实现。只要新的实现类也是基类的派生类,就可以用新的派生类实例来替换原有实例。
- 扩展性:可以很容易地添加新的派生类来扩展程序的功能,而不需要修改依赖于基类接口的代码。
代码示例
假设你有一个基类Animal
和两个派生类Dog
和Cat
。你可以有一个返回Animal
指针的函数,实际上返回的是指向Dog
或Cat
对象的指针:
class Animal //基类
{
public:
virtual void speak() = 0;//纯虚函数
};
class Dog : public Animal
{
public:
void speak() override
{
std::cout << "Woof!" << std::endl;
}
};
class Cat : public Animal
{
public:
void speak() override
{
std::cout << "Meow!" << std::endl;
}
};
std::unique_ptr<Animal> getAnimal(const std::string& type)
{
if (type == "dog")
{
//std::shared_ptr可以用new来实例化,
//但std::unique_ptr用new存在安全隐患
//所以c++14后新增std::make_shared和make_unique,
//按下面语法实例化,不用new
auto test_1 = std::make_unique<Dog>();
return test_1;
} else if (type == "cat")
{
auto test_2 = std::make_unique<Dog>();
return test_2;
}
return nullptr;
}
在这个例子中,getAnimal
函数根据传入的字符串返回指向不同派生类对象的std::unique_ptr<Animal>
。尽管返回类型是基类Animal
的智能指针,实际返回的对象可以是任何Animal
的派生类。这允许调用者使用基类接口来操作这些对象,而不用关心具体的派生类类型。当然,std::shared_ptr也支持这种特性。
注意事项
- 当通过基类指针(或智能指针)调用派生类的函数时,确保基类的函数被声明为
virtual
,这样才能正确地调用到派生类的重写或实现版本。 - 在使用
std::unique_ptr
转移所有权时要特别小心,因为它不支持拷贝操作,只能通过移动语义(std::move
)来转移所有权。