C++ C++;父类,其虚拟方法在两个不同的子类中实现

C++ C++;父类,其虚拟方法在两个不同的子类中实现,c++,class,inheritance,polymorphism,virtual,C++,Class,Inheritance,Polymorphism,Virtual,很难把这个主题的标题说得很清楚,但我会尝试解释一下上下文(下面有一些代码)。注:我已经看到类似的问题得到了回答,但他们只处理了一个儿童班的病例。所以他们对我的情况没有帮助,因为我有两个儿童班 上下文: 我有一个父类形状,它有两个子类:圆形和方形。 我将有一个形状对象的向量,但这些形状对象实际上只是圆形对象或方形对象。我需要圆形类和方形类具有相同的父类,以便可以将它们存储在同一个向量中 诀窍是,我需要使用向量中的Shape对象来调用在Circle类或Square类中实现的方法,因此,我需要在父类S

很难把这个主题的标题说得很清楚,但我会尝试解释一下上下文(下面有一些代码)。注:我已经看到类似的问题得到了回答,但他们只处理了一个儿童班的病例。所以他们对我的情况没有帮助,因为我有两个儿童班

上下文: 我有一个父类形状,它有两个子类:圆形和方形。 我将有一个形状对象的向量,但这些形状对象实际上只是圆形对象或方形对象。我需要圆形类和方形类具有相同的父类,以便可以将它们存储在同一个向量中

诀窍是,我需要使用向量中的Shape对象来调用在Circle类或Square类中实现的方法,因此,我需要在父类Shape中拥有这些方法的“虚拟”版本

下面是我的类代码的简化部分:

形状h:

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()