C++ C+多态性+;

C++ C+多态性+;,c++,C++,这是我的代码: #include <cstdlib> #include <iostream> #include <cstring> using namespace std; class person { string name; public: person(const string &n){ name=n; } virtual person& print(const person&

这是我的代码:

#include <cstdlib>
#include <iostream> 
#include <cstring>  
using namespace std;

class person {
string name;
public:

    person(const string &n){
        name=n;
    }   
    virtual person& print(const person&){}   
};

class worker:public person {
    int number;
public:
    worker(const string &n , int num ):person(n){
        number=num;
    }

    virtual worker& print(const worker& x){
        cout << number << x.number<< endl; 
        return number+=number;
    }
};

int main(int argc, char** argv) {

    person *p = new worker("john",1);
    person *g = new worker("jack",2);
    int c = p->print(*g);

    return 0;
}
#包括
#包括
#包括
使用名称空间std;
班主任{
字符串名;
公众:
人员(常量字符串和n){
name=n;
}   
虚拟人和打印(const person&){}
};
班主任:公众人士{
整数;
公众:
工作者(常量字符串&n,整数):个人(n){
number=num;
}
虚拟工作者和打印(常量工作者和x){

cout正如您已经注意到的,父类中的方法无法看到仅在其子类中定义的成员。如果您想一想,这很有意义,因为父类在编译时不可能知道其可能的子类是如何定义的,那么它如何知道其新的数据成员呢?

正确的方法是使
Person
class中的
print()
方法纯粹虚拟,并为每个子类编写一个单独的
print()
方法,因为只有子类可以访问其私有数据成员

virtual void print() = 0;

请注意,该函数不再接受参数,它在子类中的实现应该打印它们自己的
编号
,以及它们想要打印的任何其他成员。

此代码非常奇怪。要打印,您不需要传入
人员
工作者

class person
{
     public: virtual void print(){ cout << name; }
};

class worker : public person
{
     public: virtual void print(){ person::print(); cout << ": " << number; }
};

int main()
{
     person *p = new worker( "john", 1 ),
            *q = new worker( "jack", 2 );
     p->print();
     q->print();

     return 0;
}
班级人员
{

public:virtual void print(){cout您的两个
print
函数在返回和参数类型上都不同。因此它们除了名称之外没有任何共同之处。此外,在运行时,计算机不知道哪种“种类”
个人的
p
q
是指向的。因此,您需要给
打印
一个统一的签名,例如:

class Person
{
public:
    virtual int print(Person* other) {}
}
我假设您希望
print
返回
int
,因为您编写了
int c=p->print(*g);
。我还使用了一个指针来使用变量类型作为参数。在
Worker
和其他派生类中,您可以编写如下内容:

int print(Person* other)
{
    Worker* worker = dynamic_cast<Worker*>(other);
    if (worker)
    {
        std::cout << number << " " << worker->number << std::endl;
        return number += worker->number;
    }
    else
    {
        // return default value and/or make some output that cast failed
        return -1;
    }
}

这就是所谓的双重分派——同时在两个对象上执行多态性。如果使用
worker
对象作为参数调用
person
对象的打印函数,或者反过来调用
worker
对象,您希望发生什么情况?OP希望基于参数打印()我看不出这对他的情况有什么帮助。这只会导致编译器错误,因为他无法实例化工人类,除非你也建议对其进行更改。@BenjaminLindley,看看答案的文本。我让他编写一个单独的
print()
对于每个子类。您建议他给出什么签名?他已经为该子类编写了一个打印函数。问题是它的签名错误,因此不参与动态调度。但是如果他给出了正确的签名(以
人员
而不是
工作者
作为参数),函数不会编译,因为它访问
person
类没有的成员。@BenjaminLindley,非常好的观点。我已经更新了答案。我认为他接受原始答案的原因是因为他在寻找如何设计它的想法,而不是特定的代码,这显然没有解决问题m、 我写这个答案时太匆忙了(
int print(Person* other)
{
    Worker* worker = dynamic_cast<Worker*>(other);
    if (worker)
    {
        std::cout << number << " " << worker->number << std::endl;
        return number += worker->number;
    }
    else
    {
        // return default value and/or make some output that cast failed
        return -1;
    }
}
class Person
{
protected: 
    enum EPersonType {WORKER /*insert other derivats here*/};
    const EPersonType Type;

    Person(EPersonType type) : Type(type) {}
    virtual int printDetails(Person* other) {}

public:
    int print(Person* other)
    {
        if (other->Type != Type)
            return -1;
        else 
            return printDetails(other);       // you can now use safe cast inhere
    }
}

class Worker : public Person
{
public:
    Worker() : Person(WORKER) {}
    int printDetails(Person* other)
    {
        Worker* worker = static_cast<Worker*>(other);  // always works
                                                       // also possible: ...= (Worker*)other;
        //...
    } 
}