C++ C++;父类,其虚拟方法在两个不同的子类中实现
很难把这个主题的标题说得很清楚,但我会尝试解释一下上下文(下面有一些代码)。注:我已经看到类似的问题得到了回答,但他们只处理了一个儿童班的病例。所以他们对我的情况没有帮助,因为我有两个儿童班 上下文: 我有一个父类形状,它有两个子类:圆形和方形。 我将有一个形状对象的向量,但这些形状对象实际上只是圆形对象或方形对象。我需要圆形类和方形类具有相同的父类,以便可以将它们存储在同一个向量中 诀窍是,我需要使用向量中的Shape对象来调用在Circle类或Square类中实现的方法,因此,我需要在父类Shape中拥有这些方法的“虚拟”版本 下面是我的类代码的简化部分: 形状h:C++ C++;父类,其虚拟方法在两个不同的子类中实现,c++,class,inheritance,polymorphism,virtual,C++,Class,Inheritance,Polymorphism,Virtual,很难把这个主题的标题说得很清楚,但我会尝试解释一下上下文(下面有一些代码)。注:我已经看到类似的问题得到了回答,但他们只处理了一个儿童班的病例。所以他们对我的情况没有帮助,因为我有两个儿童班 上下文: 我有一个父类形状,它有两个子类:圆形和方形。 我将有一个形状对象的向量,但这些形状对象实际上只是圆形对象或方形对象。我需要圆形类和方形类具有相同的父类,以便可以将它们存储在同一个向量中 诀窍是,我需要使用向量中的Shape对象来调用在Circle类或Square类中实现的方法,因此,我需要在父类S
class Shape{
public:
std::string getColor();
virtual int getRadius() = 0; //Method implemented in Circle
virtual int getHeight() = 0; //Method implemented in Square
virtual int getWidth() = 0; //Method implemented in Square
protected:
std::string color;
};
class Circle : public Shape{
public:
int getRadius();
private:
int radius;
};
class Square : public Shape{
public:
int getHeight();
int getWidth();
private:
int height;
int width;
};
在Shape.cpp中,我有如下内容:
std::string Shape::getColor(){
return color;
}
int Circle::getRadius(){
return radius;
}
int Square::getHeight(){
return height;
}
int Square::getWidth(){
return width;
}
当我要创建圆形和方形对象时,错误发生在main.cpp中:
Circle *c = new Circle(...);//Error: cannot instantiate abstract class
//pure virtual function "Shape::getHeight" has no overrider
//pure virtual function "Shape::getWidth" has no overrider
Square *s = new Square(...);//Error: cannot instantiate abstract class
//pure virtual function "Shape::getRadius" has no overrider
因此,似乎我需要在Square类中声明“getRadius”,在Circle类中声明“getHeight”和“getWidth”
我试着用virtual添加它们,但这会产生圆形和方形抽象类,所以我不能用它们创建任何对象
有没有办法让这一切顺利进行
这是我在stackoverflow上发布的第一个问题。我希望一切都清楚。谢谢你的帮助 我希望您知道
纯虚拟
和纯虚拟
函数之间的区别<代码>纯虚拟函数本质上是带有无主体的占位符函数。shape的基类更适合于普通虚拟函数,这些函数可以在子类中更改,但不必在子类中更改。取出函数声明中的=0
部分,使函数成为普通的虚拟的函数。这将使您朝着正确的方向前进。通过使您的成员不是纯虚拟的,您可以在派生类中实现它们,但不必这样做
class Shape{
public:
std::string getColor();
virtual int getRadius(); //Method implemented in Circle
virtual int getHeight(); //Method implemented in Square
virtual int getWidth(); //Method implemented in Square
protected:
std::string color;
};
class Circle : public Shape{
public:
int getRadius();
private:
int radius;
};
class Square : public Shape{
public:
int getHeight();
int getWidth();
private:
int height;
int width;
};
您的虚拟方法并不是虚拟方法的理想候选方法,因为它们对一个类有特定的功能,但对另一个类没有用处
虚拟方法的一个很好的例子是由每个类实现的东西,但具有不同的功能或结果,如virtualint-area()
或virtual-bool-intersects(Shape*otherShape)
等等
无论如何,这就是编译代码的方式(附带一些额外内容):
形状:
class Shape{
public:
std::string getColor();
Shape() {}
virtual ~Shape() {}
virtual int getRadius() { return 0; } // no pure virtual
virtual int getHeight() { return 0; } // no pure virtual
virtual int getWidth() { return 0; } // no pure virtual
protected:
std::string color;
};
class Circle : public Shape {
public:
Circle( int r )
: Shape()
, radius( r )
{}
Circle() : Circle( 0 ) {}
~Circle() { std::cout << __PRETTY_FUNCTION__ << std::endl; }
int getRadius() override { return radius; };
private:
int radius;
};
以下是虚拟方法在面积示例中的更好使用:
#include <iostream>
#include <vector>
struct Shape {
Shape() {}
virtual ~Shape() {}
virtual double area() = 0;
};
您必须至少在每个派生类中为您在Shape
中声明的纯虚拟函数定义一个主体,或者这些类成为抽象基类并且无法实例化。此外,您应该从Shape
继承,而不是Shapes
。我修复了它。谢天谢地,这种设计尝试毫无意义,也无法添加任何内容。父类必须只有所有子类通用的接口、句号、无“如果”、“但是”或“如何”。如上所述,您应该重新考虑您的设计,而不是试图编译设计糟糕的类。shape类应仅包含对所有形状通用的成员。即使是空的基类也比当前的基类好。这是我以前做的,但是,我不需要在Shape.cpp文件中为它们提供一个空的主体吗?如果我这样做了,那么当我从向量中的形状对象调用方法时,它不会使用空体定义的函数吗?而不是使用圆形或方形类中的正确选项?我可以添加一些代码来解释如何使用形状对象的向量。我尝试过这样做,但这意味着我必须给那些“形状”实体中的虚拟方法,对吗?我可以使它成为一个空体,但是每当我从向量中的一个形状对象调用例如getRadius()时,它都会使用这个空体而不是Circle类中的那个,不是吗?这可能有点奇怪,但我需要能够使用向量中的形状对象调用getRadius()(该对象最初将创建为一个圆),并使其执行Circle::getRadius(){…}@JLuc5中定义的操作。如果您所说的形状对象是,Shape myShape
,那么是的,它将调用空体。但是,Shape*myShape=new Circle()
不会。Shape*myShape=new Circle()。。。我可能需要试一试。我不知道你能做到。谢谢这听起来是个有趣的方法。明天我将在我的代码中测试它。我有一个简短的问题要问你。“for(Shape*sh:s)”与使用迭代器相同:“for(vector::iterator sh=objects.begin();sh!=objects.end();++sh){(*sh)->area()}。非常感谢!这将使代码得到编译,但不会给它增加任何意义。你可以得到各种各样的垃圾进行编译。目标不是要有这些,而是要有一个合理的设计,你可以使用。这不是一个家庭作业,我试着用OpenFrameworks绘制东西,我需要一个包含我所有形状的向量。这就是为什么我需要e父类。我想我可以有两个向量,一个代表圆,一个代表正方形,但这并没有那么好;@n.m.如果你不喜欢关于虚拟函数的建议,它隐藏了每个类需要做什么的细节,我很抱歉,或者你可能没有读完整的答案?…我不断地在页面上滚动手指,我会我看不到你的答案——如果你提供了有趣的观点,我和我确信的其他任何人都会立即投票…@n.m.如果你真的看起来像一个
int main() {
using shapes = std::vector< Shape * >;
shapes s;
s.push_back( new Circle( 10 ) );
s.push_back( new Square() );
s.push_back( new Square( 1, 3 ) );
s.push_back( new Circle() );
for ( Shape * sh : s ) {
std::cout
<< " r " << sh->getRadius()
<< " h " << sh->getHeight()
<< " w " << sh->getWidth()
<< std::endl;
}
for ( Shape * sh : s ) { delete sh; } s.clear();
}
r 10 h 0 w 0
r 0 h 0 w 0
r 0 h 1 w 3
r 0 h 0 w 0
virtual Circle::~Circle()
virtual Square::~Square()
virtual Square::~Square()
virtual Circle::~Circle()
#include <iostream>
#include <vector>
struct Shape {
Shape() {}
virtual ~Shape() {}
virtual double area() = 0;
};
struct Circle : public Shape {
Circle( int r )
: Shape()
, radius( r )
{}
Circle() : Circle( 0 ) {}
~Circle() { std::cout << __PRETTY_FUNCTION__ << std::endl; }
virtual double area() override { return radius * radius * 3.14; }
int radius;
};
struct Square : public Shape {
Square( int h, int w )
: Shape()
, height( h )
, width( w )
{}
Square() : Square( 0, 0 ) {}
~Square() { std::cout << __PRETTY_FUNCTION__ << std::endl; }
virtual double area() override { return height * width; }
int height;
int width;
};
int main() {
using shapes = std::vector< Shape * >;
shapes s;
s.push_back( new Circle( 1 ) );
s.push_back( new Square( 1, 1 ) );
s.push_back( new Square( 2, 3 ) );
s.push_back( new Circle( 2 ) );
for ( Shape * sh : s ) {
std::cout << sh->area() << std::endl;
}
for ( Shape * sh : s ) { delete sh; } s.clear();
}
3.14
1
6
12.56
virtual Circle::~Circle()
virtual Square::~Square()
virtual Square::~Square()
virtual Circle::~Circle()