You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++14继承类工厂实现遇E0269错误:求正确实现方式

C++14继承类工厂实现问题解答

问题描述

尝试实现一个动物类工厂,通过GetAnimal函数传入动物名称返回对应子类实例,但编译时出现错误:

E0269   conversion to inaccessible base class "Animal" is not allowed

原代码如下:

#include <iostream>

class Animal
{
public:
    virtual std::string Sound();
};

class Dog : Animal
{
public:
    std::string Sound() {return "Woff!";};
};

class Cat : Animal
{
public:
    std::string Sound() {return "Meow!";};
};

class Snake : Animal
{
public:
    std::string Sound() {return "Ssss!";};
};

Animal GetAnimal(std::string name)
{
    if (name == "Dog")
        return Dog();
    else if (name == "Cat")
        return Cat();
    else if (name == "Snake")
        return Snake();

    return Animal();
}

int main()
{
    std::cout << "Sound of a dog: \"" << GetAnimal("Dog").Sound() << "\"\n";
    std::cout << "Sound of a cat: \"" << GetAnimal("Cat").Sound() << "\"\n";
    std::cout << "Sound of a snake: \"" << GetAnimal("Snake").Sound() << "\"\n";

    return 0;
}

错误原因分析

1. 私有继承导致的访问权限问题

C++中使用class定义子类时,默认继承方式是private继承,这意味着基类Animal在子类中是私有成员,外部代码无法将子类对象隐式转换为基类对象,因此return Dog();这类语句会触发"无法转换到不可访问基类"的错误。

2. 对象切片问题(即使解决权限问题后仍会出现)

如果将继承改为public,GetAnimal返回Animal对象时会发生对象切片:子类对象被截断为基类对象,子类特有的信息丢失,多态机制失效——调用Sound()时只会执行基类的版本,无法触发子类的重写逻辑。

正确实现方式

步骤1:修改为public继承

将所有子类的继承方式改为public,确保基类接口对外可见:

class Dog : public Animal { ... };
class Cat : public Animal { ... };
class Snake : public Animal { ... };

步骤2:使用指针/智能指针实现多态

工厂函数需要返回基类的指针或智能指针,避免对象切片,同时保证多态生效。推荐使用std::unique_ptr来自动管理内存,避免内存泄漏:

修正后的完整代码:

#include <iostream>
#include <memory>
#include <string>

class Animal
{
public:
    // 纯虚函数,确保基类是抽象类,不能实例化
    virtual std::string Sound() const = 0;
    // 虚析构函数,确保子类对象能正确被销毁
    virtual ~Animal() = default;
};

class Dog : public Animal
{
public:
    std::string Sound() const override { return "Woff!"; }
};

class Cat : public Animal
{
public:
    std::string Sound() const override { return "Meow!"; }
};

class Snake : public Animal
{
public:
    std::string Sound() const override { return "Ssss!"; }
};

std::unique_ptr<Animal> GetAnimal(const std::string& name)
{
    if (name == "Dog")
        return std::make_unique<Dog>();
    else if (name == "Cat")
        return std::make_unique<Cat>();
    else if (name == "Snake")
        return std::make_unique<Snake>();

    // 返回空指针表示无效输入
    return nullptr;
}

int main()
{
    auto dog = GetAnimal("Dog");
    if (dog)
        std::cout << "Sound of a dog: \"" << dog->Sound() << "\"\n";

    auto cat = GetAnimal("Cat");
    if (cat)
        std::cout << "Sound of a cat: \"" << cat->Sound() << "\"\n";

    auto snake = GetAnimal("Snake");
    if (snake)
        std::cout << "Sound of a snake: \"" << snake->Sound() << "\"\n";

    return 0;
}

额外优化点

  • 将Sound()声明为const成员函数(因为该函数不修改对象状态),并使用override关键字明确标注重写,提升代码可读性和安全性。
  • 将Animal的Sound()设为纯虚函数,使Animal成为抽象类,避免意外实例化基类对象。
  • 添加虚析构函数,确保通过基类指针销毁子类对象时能正确调用子类的析构函数。
  • 使用const std::string&作为函数参数,避免不必要的字符串拷贝。

内容的提问来源于stack exchange,提问作者Runsva

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 05:33:19