代码之家  ›  专栏  ›  技术社区  ›  JLuc5

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

  •  4
  • JLuc5  · 技术社区  · 11 年前

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

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

    诀窍是我需要使用向量中的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”。。。

    我尝试用虚拟添加它们,但这使Circle和Square成为抽象类,因此我无法用它们创建任何对象。

    有没有办法使这项工作?

    这是我在stackoverflow上发布的第一个问题。我希望一切都清楚。谢谢你的帮助!

    3 回复  |  直到 11 年前
        1
  •  2
  •   stefanB    11 年前

    您的虚拟方法不是真正适合虚拟方法的候选方法 因为它们对一个类具有特定功能,但对另一个类没有用处。

    虚拟方法的一个很好的例子是每个类都实现了一些功能或结果不同的东西,比如 virtual int 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;
    };
    

    正方形:

    class Square : public Shape {
    public:
        Square( int h, int w )
            : Shape()
            , height( h )
            , width( w )
        {}  
    
        Square() : Square( 0, 0 ) {}
        ~Square() { std::cout << __PRETTY_FUNCTION__ << std::endl; }
    
        int getHeight() override { return height; }
        int getWidth() override { return width; }
    
    private:
        int height;
        int width;
    };  
    

    测试:

    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()
    
        2
  •  0
  •   yizzlez    11 年前

    我希望你知道两者之间的区别 pure virtual 而且只是 virtual 功能。 Pure virtual 函数本质上是占位符函数 身体你的基本型更适合普通型 事实上的 函数,这些函数可以但不必在子类中更改。取出 = 0 函数声明的一部分,使函数变得简单 事实上的 功能。

        3
  •  0
  •   larrylampco    11 年前

    这会让你朝着正确的方向前进。通过使成员不是纯虚拟的,如果需要,可以在派生类中实现它们,但不必这样做。

    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;
    };