为什么不能将多态派生 class 嵌套在基础 class 中?
Why can't polymorphic derived classes be nested inside the base class?
例如,我尝试做这样的事情:
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!";
}
};
};
编译器抱怨 Animal
是一个不完整的类型。但是为什么 Animal
是一个不完整的类型,如果不需要内部 class 定义来定义外部 class 本身(因为内部 class 类型没有非静态变量在外部 class)?
中按值声明
是否有解决此问题的方法或更好的方法来完成我想做的事情?
Is there a way around this or a better way to do what I'm trying to do?
不要使用嵌套的 classes。只需将派生的 classes 移出 Animal
.
单独说明,具有函数
static Animal *makeLion() { return new Lion(); }
static Animal *makeTiger() { return new Tiger(); }
static Animal *makePig() { return new Pig(); }
in Animal
是设计不佳的症状。基础 class 应该尽可能地与从它派生的 class 无关。
这里有一个更简洁的界面和实现的建议:
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:
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 class 在 class 定义的右大括号 }
之前是不完整的。
关于“有没有办法解决这个问题”,你可以这样做:
struct A
{
struct B;
};
struct A::B
: A
{};
但这不是常见的模式。我不记得曾经看过它。
一个可能的解决方案是将 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.
糟糕的设计。制作对象不应该在 Animal class 中完成。考虑像这样重新设计 classes:
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!";
}
};
然后像这样使用:
Animal* p = new Pig;
cout << p->says() << endl;
否则,每次添加新种类时都必须添加 makeXXX() 函数。
例如,我尝试做这样的事情:
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!";
}
};
};
编译器抱怨 Animal
是一个不完整的类型。但是为什么 Animal
是一个不完整的类型,如果不需要内部 class 定义来定义外部 class 本身(因为内部 class 类型没有非静态变量在外部 class)?
是否有解决此问题的方法或更好的方法来完成我想做的事情?
Is there a way around this or a better way to do what I'm trying to do?
不要使用嵌套的 classes。只需将派生的 classes 移出 Animal
.
单独说明,具有函数
static Animal *makeLion() { return new Lion(); }
static Animal *makeTiger() { return new Tiger(); }
static Animal *makePig() { return new Pig(); }
in Animal
是设计不佳的症状。基础 class 应该尽可能地与从它派生的 class 无关。
这里有一个更简洁的界面和实现的建议:
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:
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 class 在 class 定义的右大括号 }
之前是不完整的。
关于“有没有办法解决这个问题”,你可以这样做:
struct A
{
struct B;
};
struct A::B
: A
{};
但这不是常见的模式。我不记得曾经看过它。
一个可能的解决方案是将 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.
糟糕的设计。制作对象不应该在 Animal class 中完成。考虑像这样重新设计 classes:
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!";
}
};
然后像这样使用:
Animal* p = new Pig;
cout << p->says() << endl;
否则,每次添加新种类时都必须添加 makeXXX() 函数。