派生类忽略基类函数

时间:2014-12-12 04:47:07

标签: c++ inheritance

我正在做关于C ++继承的家庭作业,我无法理解为什么在我的代码中发生这种情况。我有一个从类类派生的Triangle类,程序没有按照我期望的方式运行。在Main.cpp文件中,创建了一个Triangle对象并调用了draw()函数,我希望这个函数调用figure.cpp中定义的函数,但它似乎调用了在triangle.cpp中定义的函数。 。我认为只有在使用关键字virtual定义函数时才会出现这种情况?

对于作业,我必须找到两个场景的程序输出:一个是使用关键字virtual,另一个是不使用关键字virtual。我的程序现在对两种情况都有相同的输出。我已经通过打印一个语句来实现这些函数,以显示调用哪个版本的函数。我相信这是在派生类中重新定义函数的正确方法。

的main.cpp

#include <iostream>
#include "figure.h"
#include "triangle.h"

using std::cout;

int main()
{
  Triangle tri;

  //This function should invoke the one from figure.cpp
  tri.draw();  

  return 0;
}

figure.h

#ifndef _FIGURE_H_
#define _FIGURE_H_
#include <iostream>

class Figure {
    public: 
        Figure();

        void draw();
        void erase();
        void center();  

};

#endif

figure.cpp

#include "figure.h"

Figure::Figure() {

}

void Figure::draw() {
    std::cout << "Calling Figure::draw()" << std::endl;
}

void Figure::erase() {
    std::cout << "Calling Figure::erase()" << std::endl;
}

void Figure::center() {
    std::cout << "Calling Figure::center()" << std::endl;
}

triangle.h

#ifndef _TRIANGLE_H_
#define _TRIANGLE_H_
#include <iostream>
#include "figure.h"

class Triangle : public Figure {
    public:

        Triangle();

        void draw();

        void erase();

        void center();  
    private:

        double base;
        double height;
        double centerPoint;


};

#endif

triangle.cpp

#include "triangle.h"
Triangle::Triangle() {

    base = 0.0;
    height = 0.0;
    centerPoint = 0.0;

}

void Triangle::draw() {
    std::cout << "Calling Triangle::draw()" << std::endl;
}

void Triangle::erase() {
    std::cout << "Calling Triangle::erase()" << std::endl;
}

void Triangle::center() {
    std::cout << "Calling Triangle::center()" << std::endl;
}

* UPDATE

我创建了另一个不使用单独编译的程序,它给了我我期望的东西。为什么单独的编译导致不同的结果?下面是我正在测试的代码,它没有使用单独的编译。在main中调用draw()调用图中定义的函数,如果我取消注释函数声明,则调用Triangle中的函数。

#include <iostream>

using namespace std;

class Figure {

    public:
        Figure() {

        }

        void draw() {
            cout << "Calling Figure::draw()" << endl;
        }

};

class Triangle : public Figure {
    public:
        Triangle() {

        }

//      void draw() {
//          cout << "Calling Triangle::draw()" << endl;
//      }



};


int main () {

    Triangle tri;

    tri.draw();

    return 0;
}

2 个答案:

答案 0 :(得分:3)

Triangledraw继承Figure函数。

这意味着,如果您从void draw();删除了Triangle的声明,那么您仍然可以在tri.draw()内调用main } function,它会调用Figure::draw

但是,当您 void draw();内声明Triangle时,它实际上替换从{继承的draw函数{1}},并且好像你从未从Figure继承它。

因此,如果您希望它从Figure调用draw函数,则一个选项是在Triangle中替换它。

另一种选择是让FigureTriangle::draw的函数体内手动调用Figure::draw

关键字Triangle::draw做了不同的事情:它允许发生相反的效果 假设您声明:

virtual

对于所有编译器都可以看出,Figure & f = tri; f.draw(); 是对图的引用,并且可以引用任何类型的任何图形。
但是,在这种情况下,如果f函数声明为draw,它将允许程序在运行时确定图virtual引用的确切类型,从而允许程序为f的任何派生类型的任何给定引用调用draw的正确版本。

答案 1 :(得分:1)

编译器正在做正确的事情: tri.draw();应该执行Triangle::draw()

调用

Triangle::draw()因为类型(Triangle)已知。作为非虚函数,编译器选择在编译时调用的正确函数。这称为静态分派。另一个选项是在运行时,称为动态调度

所以第一部分是找出使用Figure::draw()调用tri的语法。除了行tri.draw();

之外,您的代码似乎无需更改

第二部分是弄清楚如何使用动态调度,您需要修改Figure

我停在那里,因为这是家庭作业。