简体   繁体   English

为什么不能将多态派生类嵌套在基类中?

[英]Why can't polymorphic derived classes be nested inside the base class?

For example, I tried to do something like this: 例如,我试图做这样的事情:

class Animal {
public:
    virtual const char *says() const = 0;

    static Animal *makeLion() { return new Lion(); }
    static Animal *makeTiger() { return new Tiger(); }
    static Animal *makePig() { return new Pig(); }

private:
    class Lion : public Animal { // error: invalid use of incomplete type ‘class Animal’
    public:
        virtual const char *says() const
        {
            return "roar";
        }
    };

    class Tiger : public Animal { // error: invalid use of incomplete type ‘class Animal’
    public:
        virtual const char *says() const
        {
            return "meow";
        }
    };

    class Pig : public Animal { // error: invalid use of incomplete type ‘class Animal’
    public:
        virtual const char *says() const
        {
            return "That\'s all Folks!";
        }
    };
};

The compiler complains that Animal is an incomplete type. 编译器抱怨Animal是不完整的类型。 But why is Animal an incomplete type, if the inner class definitions are not needed to define the outer class itself (since no non-static variables of the inner class types are declared by value in the outer class)? 但是,如果不需要内部类定义来定义外部类本身,为什么Animal是不完整的类型(因为外部类中没有通过值声明内部类类型的非静态变量)?

Is there a way around this or a better way to do what I'm trying to do? 有没有办法解决这个问题,或者有更好的方法来做我想做的事情?

A class is not complete until the closing brace } of the class definition. 直到类定义的右括号}为止,一个类才是完整的。

Re “is there a way around this”, you can do things like this: 关于“是否有解决办法”,您可以执行以下操作:

struct A
{
    struct B;
};

struct A::B
    : A
{};

But it's not a common pattern. 但这不是常见的模式。 I can't remember ever having seen it. 我不记得曾经看过它。

Is there a way around this or a better way to do what I'm trying to do? 有没有办法解决这个问题,或者有更好的方法来做我想做的事情?

Don't use nested classes. 不要使用嵌套类。 Just move the derived classes out of Animal . 只需将派生类移出Animal


On a separate note, having functions 另外,具有功能

static Animal *makeLion() { return new Lion(); }
static Animal *makeTiger() { return new Tiger(); }
static Animal *makePig() { return new Pig(); }

in Animal is a symptom of poor design. Animal中的一个症状是设计不佳。 A base class should, as much as possible, be agnostic of classes derived from it. 基类应尽可能与从其派生的类无关。


Here's a suggestion for a cleaner interface and implementation: 这是一个更清洁的界面和实现的建议:

Animal.h: Animal.h:

namespace AnimalsNamespace
{
   // The base class
   class Animal
   {
      public:
         virtual const char *says() const = 0;
   };


   // Functions to construct objects of various sub-types of Animal.
   // Moving these out of Animal and putting them in the namespace makes
   // Animal a little bit cleaner.

   Animal* makeLion();
   Animal* makeTiger();
   Animal* makePig();
}

Animal.cpp: Animal.cpp:

namespace AnimalsNamespace
{
   class Lion : public Animal
   {
      public:
         virtual const char *says() const
         {
            return "roar";
         }
   };

   class Tiger : public Animal
   {
      public:
         virtual const char *says() const
         {
            return "meow";
         }
   };

   class Pig : public Animal
   {
      public:
         virtual const char *says() const
         {
            return "That\'s all Folks!";
         }
   };

   Animal* makeLion() { return new Lion(); }
   Animal* makeTiger() { return new Tiger(); }
   Animal* makePig() { return new Pig(); }
}

A possible solution is to put definition of Lion, Tiger, Pig in function scope: 一个可能的解决方案是将Lion,Tiger,Pig的定义放在函数范围内:

class Animal {
public:
    virtual ~Animal() = default;
    virtual const char *says() const = 0;

    static std::unique_ptr<Animal> makeLion()
    {
        class Lion : public Animal
        {
        public:
            virtual const char *says() const override
            {
                return "roar";
            }
        };
        return std::make_unique<Lion>();
    }
    static std::unique_ptr<Animal> makeTiger() {
        class Tiger : public Animal
        {
        public:
            virtual const char *says() const override
            {
                return "meow";
            }
        };
        return std::make_unique<Tiger>();
    }
    static std::unique_ptr<Animal> makePig() {
        class Pig : public Animal
        {
        public:
            virtual const char *says() const override
            {
                return "That\'s all Folks!";
            }
        };
        return std::make_unique<Pig>();
    }
};

int main() {    
    std::cout << Animal::makeLion()->says() << std::endl;
}

Demo . 演示

Bad design. 设计不良。 Making an object should not be done in Animal class. 动物类中不应创建对象。 Consider redesigning the classes like: 考虑重新设计如下类:

class Animal
{
public:
    virtual const char* says() const = 0;
};

class Lion : public Animal
{
public:
    virtual const char *says() const
    {
        return "roar";
    }
};

class Tiger : public Animal
{
public:
    virtual const char *says() const
    {
        return "meow";
    }
};

class Pig : public Animal
{
public:
    virtual const char *says() const
    {
        return "That\'s all Folks!";
    }
};

And then use like this: 然后像这样使用:

Animal* p = new Pig;
cout << p->says() << endl;

Otherwise, you have to add makeXXX() functions every time you add a new kind. 否则,每次添加新种类时,都必须添加makeXXX()函数。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 非多态派生类的基类 - Base class of non polymorphic derived classes 如何访问不在基 class 中的派生类中的 STL 类的成员函数? (正文中的详细解释) - How can I access member functions of STL classes inside derived classes that aren't in the base class? (detailed explanation in body) 为什么不能将基类对象分配给派生类对象? - Why can't a Base class object be assigned to a Derived class object? 为什么使用基类指针来派生类 - Why use base class pointers for derived classes 当调用派生类对象时,为什么`this`无法从基类方法访问派生类成员 - Why `this` can't access the derived class members from base class methods when called for derived class object 为什么我不能访问静态多态派生类中的受保护成员? - Why can't I access protected member in static polymorphic derived class? 为什么派生类不能访问基类的静态方法? - Why don't derived classes have access to base class static methods? 当基类不是多态而是派生时,'this'地址不匹配 - Mismatch of 'this' address when base class is not polymorphic but derived is 派生的 class 嵌套在基础 class - C++ - Derived class nested inside base class - C++ 多态类的typeid,当给定一个指向派生类的指针时,表示它是一个指向基类的指针! 为什么? - typeid of a polymorphic class, when given a pointer to a derived class, says it's a pointer to base class! why?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM