对于下面的代码,当基类指针被分配给派生类时,我有关于多态性的问题。
当派生类的对象直接使用print函数时,输出是显而易见的。
当我使用基类指针并指向派生类的对象时,会使用基类的print函数,但输出的是派生对象的信息。有人能详细解释一下吗?谢谢!
class Person {
public:
Person() {};
Person(string nm):name(nm) {};
void print() const;
private:
string name;
};
class Student : public Person {
public:
Student(int num, string nm) : IDNumber(num), Person(nm) {};
void print() const;
private:
int IDNumber;
}
class Employee : public Person {
public:
Employee(int num, int sal, string nm) : IDNumber(num), salary(sal), Person(nm) {};
void print() const;
private:
int IDNumber, salary;
}
void Person::print() const {
cout << name << endl;
}
void Student::print() const {
cout << "GoGoGo! ";
Person::print();
}
void Employee::print() const {
cout << "I work: ";
Person::print();
}
int main() {
Person per("Peter");
Student stu(3141, "Sally");
Employee emp(2718, 40, "Edward");
Person* ptr = &per;
Person* ptr2 = &stu;
Person* ptr3 = &emp;
per.print(); //Peter
stu.print(); //GoGoGo! Sally
emp.print(); //I work: Edward
ptr->print(); //Peter
ptr2->print(); //Sally
ptr3->print(); //Edward
return 0;
}
代码行为的关键词是“静态绑定和动态绑定”。
当编译器在编译时读取下面的语句时,它看到ptr3是person类型的,它检查Person类并用Person类中定义的print函数地址替换print()。所有这些都发生在编译时,这就是为什么叫做静态绑定。
ptr3->print();
为什么它能够打印通过派生类对象输入的信息?
在下面的语句中,您调用基类的构造函数并在基类成员中输入信息。ptr3*属于基类类型,因此它可以访问其成员。
Employee(int num, int sal, string nm) : IDNumber(num), salary(sal), Person(nm) {};
如果,你赚了int工资;员工类中的公共成员,并尝试通过以下方式访问
ptr3-
它会给出错误
ptr3没有指定薪金的成员
因为salary是派生类的成员,基类对象无法访问它。
函数< code>print()不是< code >虚拟的,因此不是多态的。基类上的函数隐藏了子类的函数。
要使代码按预期工作,您唯一要做的就是在类< code>Person中使< code>print()成为虚拟的:
class Person {
public:
Person() {};
virtual ~Person() {};
Person(string nm):name(nm) {};
virtual void print() const;
private:
string name;
};
请注意,我添加了一个虚拟析构函数,这是每个要继承的类所必需的。
输出显示了派生对象的信息,因为子类继承了基类的成员(即< code>name,它被设置为Peter、Sally和Edward)。
首先,我不确定如何准确地用一行来描述我在做什么...因此标题有点模糊。 我能给出的问题的最短描述是“我有一个函数,它应该能够将许多可能的类类型中的任何一个作为参数,这些类都是从基类派生的”。 具体来说,我有两个类别的类,它们都实现了不同类型的方法,它们很相似,但不完全相同。 也许我只是举个例子会更好?你会看到我用指针类型转换做了一些稍微奇怪的事情。我不认为这些是好的编程实践。它们至少有点奇怪,我想
一个类的对象经常会是另一个类的对象。例如,矩形当然是四边形(正方形、平行四边形和梯形也是这样),因此可以说矩形类 Rectangle 是从四边形类 Quadrilateral 继承而来的。在本例中,类 Quadrilateral 叫做基类,类 Rectangle 称为派生类。矩形是四边形的一种特殊类型,但是要说四边形是矩形则是不正确的。图 9.1 示例了几个简单的继承例子。 基类 派生类 stud
从已有的对象类型出发建立一种新的对象类型,使它部分或全部继承原对象的特点和功能,这是面向对象设计方法中的基本特性之一。继承不仅简化了程序设计方法,显著提高了软件的重用性,而且还使得软件更加容易维护。派生则是继承的直接产物,它通过继承已有的一个或多个类来产生一个新的类,通过派生可以创建一种类族。 继承 基本概念 在定义一个类A时,若它使用了一个已定义类B的部分或全部成员,则称类A继承了类B,并称
我无法将派生类传递给接受基类作为参数的函数。基类由“障碍物”组成,这些障碍物将被放置在“板”上。无效的board::setvalue(int-length、int-width、board 但是,这会导致编译器给出“未知参数转换…”错误。在浏览站点时,我发现我应该将派生对象作为常量进行传递,但这会导致问题,因为无法将常量分配给线路板(因为它包含指向非常量障碍物的指针)。 反过来,将线路板更改为包含常
假设我有一个没有数据的类: 和派生类 Empty类的对象的大小为1。派生类的空部分的大小通常为0。据我所知,编译器看到基Empty类没有数据,因此它可以优化Empty的大小,以防它“在”Derived中,但标准并不要求这样做。 所以问题是: 我能在编译时确定Derived类的Empty部分并没有占用内存吗。 我知道我可以像一样进行检查...但它太冗长了,并且有几个类,如派生。有没有更优雅的解决方案