从基类派生函数

Deriving functions from a base class

本文关键字:函数 派生 基类      更新时间:2023-10-16

我可能走错了路。我被要求创建一个特定类的对象数组。但是,这个类有两个派生类。

class Employee {
     // Some stuff here about the backbone of the Employee class
}
class Salary: public Employee {
     // Manipulation for Salary employee
}
class Hourly: public Employee {
     // Manipulation for hourly Employee 
}
// Main Program
int main (int argc, char**argv) {
Employee data[100]; // Creates an array of Employee objects
while (employeecount > 100 || employeecount < 1) {
    cout << "How many employees? ";
    cin >> employeecount;       
}
for(int x = 0; x <= employeecount; x++) {
    while (status != "S" || status != "s"|| status != "H" || status != "h") {
        cout << "Employee Wage Class (enter H for hourly or S for Salary)";
        cin >> status;
    }

    if (status == "S" || status == "s") { // Salaried Employee
        new 
    } else { // We valid for hourly or salary, so if its not Salaried it's an hourly
    }
}
     return 0;
}

我想问的问题是,基类可以调用派生类的方法吗?例如,如果我为Salary类创建了一个名为getgross的方法:我可以像这样调用Employee.getgross()吗?如果不是,我怎么能调用子类的方法?

为了避免切片,您需要存储指向对象的指针

Employee* data[100];

然后你可以从各种派生类中创建对象并将它们放入数组中,例如

data[0] = new Salary;

为了使正确的方法被调用,你需要在基类中声明一个虚方法,然后在派生类中重写它。

Employee类中声明getgross()virtual

的例子:

class Employee {
     virtual int getgross();
}
class Salary: public Employee {
     virtual int getgross();
}

在指向Salary对象的Employee*上调用getgross()时,将调用Salarygetgross()
我也将virtual添加到Salary::getgross()中,目前不需要,但现在最好包含它,因为以后您可能想要派生Salary的类。

数组必须是指针数组,以避免切片问题。使用vector的智能指针会更好。

最好的方法是在基类(虚方法)中使用getGross()方法,以便派生类可以继承它。

正如大家所说,你必须使用指针指向Employee对象,而不是数组中的Employee对象。这样,Employee的任何派生类都可以被Employee指针指向。

我认为你要做的是实现员工基类中的方法,并使其可用于所有派生类。如果是,下面应该是你的答案。

(从这里借用这个答案):

如何在我的派生类的成员函数调用相同的函数从它的基类?

"使用基地::f ();

让我们从一个简单的例子开始。当调用非虚函数时,编译器显然不使用虚函数机制。相反,它使用成员函数的完全限定名按名称调用函数。例如,下面的c++代码…

void mycode(Fred* p)
{
p->goBowling();  // Pretend, Fred::goBowling() is non-virtual

}

…可能会被编译成类似c语言的代码(p形参变成了成员函数中的this对象):

void mycode(Fred* p)
{
__Fred__goBowling(p);  // Pseudo-code only; not real
}

实际的名称混淆方案比上面暗示的简单方案要复杂得多,但是您可以理解。关键是这个特殊的情况没有什么奇怪的——它被解析成一个类似printf()的普通函数。

现在对于上面的问题所处理的情况:当您使用虚函数的全限定名(类名后面跟着"::")调用虚函数时,编译器不使用虚函数调用机制,而是使用与调用非虚函数相同的机制。换句话说,它按名称而不是按槽号调用函数。因此,如果您希望派生类Der中的代码调用Base::f(),即在其基类Base中定义的f()版本,您应该编写:

void Der::f()
{
Base::f();  // Or, if you prefer, this->Base::f();
}

编译器会把它变成类似下面的东西(再次使用过于简单的名称混淆方案):

void __Der__f(Der* this)  //Pseudo-code only; not real
{
    __Base__f(this);        // Pseudo-code only; not real
}

"

几点思考:

  1. 你需要存储一个指针数组的员工。一个简单的employee数组是行不通的。每当你向数组中添加Employee时,它将被"截断"到基类,并且任何额外的信息将丢失。你可以使用dynamic_cast测试指针的类型,所以你可以在调用之前检查类型。否则,在给定基类指针(或引用)的情况下,不能调用纯派生成员函数。
  2. 旧的指导原则"更喜欢遏制而不是继承"可以以一种完全不同的方式解决问题。只需将pay类型设置为Employee的属性,并完全失去继承。