我正在做关于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;
}
答案 0 :(得分:3)
Triangle
从draw
继承Figure
函数。
这意味着,如果您从void draw();
删除了Triangle
的声明,那么您仍然可以在tri.draw()
内调用main
} function,它会调用Figure::draw
。
但是,当您 在void draw();
内声明Triangle
时,它实际上替换从{继承的draw
函数{1}},并且好像你从未从Figure
继承它。
因此,如果您希望它从Figure
调用draw
函数,则一个选项是不在Triangle中替换它。
另一种选择是让Figure
在Triangle::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
。
我停在那里,因为这是家庭作业。