2016-05-05 8 views
0

Wie kann ich abgeleitete Klasse Mitgliedsfunktion ohne virtuellen Schlüssel erreichen.Wie vermeidet man das virtuelle Schlüsselwort

#include<iostream> 
using namespace std; 
class Employee{ 
public: 
    void what(){ 
     cout<<"Employee"<<endl; 
    } 
}; 
class Secretary:public Employee{ 
    public: 
    void what(){ 
     cout<<"Secretary"<<endl; 
    } 
}; 
class Manager:public Employee{ 
    public: 
    void what(){ 
     cout<<"Manager"<<endl; 
    } 
}; 
class Director:public Manager{ 
    public: 
    void what(){ 
     cout<<"Director"<<endl; 
    } 
}; 
void f(Employee*); 
int main(){ 
    Employee a; 
    Manager b; 
    Director c; 
    Secretary d; 
    f(&a); 
    f(&b); 
    f(&c); 
    f(&d); 
    return 1; 
} 
void f(Employee *a){ 
    a->what(); 
} 

Es druckt immer "Mitarbeiter". Ich möchte den Klassennamen jedes Objekts drucken. und a.what() druckt den Klassennamen korrekt. Aber ich muss Zeiger und f (Mitarbeiter *) Funktion für diese Aufgabe verwenden.

+1

Sie eine Kennung es in jeder Art, wie, welche Art setzen kann:

void f(Employee*a) { a->what(); } void f(Secretary*a) { a->what(); } void f(Manager*a) { a->what(); } void f(Director*a) { a->what(); } 

Sie eine Vorlage statt Schreiben Sie die vier Kopien verwenden könnte ist .. Mitarbeiter = 1, Manager = 2, Direktor = 3 und schalten Sie das ein. Es gibt auch etwas namens "getagged Versand" https://crazycpp.wordpress.com/2014/12/15/tutorial-on-tag-dispatching/ – xaxxon

+2

Sie können nicht. Virtuelle Funktionen sind ** der einzige Grund, warum abgeleitete Klassen existieren. Beschreibt Ihre Aufgabe, dass Sie keine virtuellen Funktionen verwenden sollten? Wenn ja, fallen Sie aus. –

+3

Sie könnten den statischen Versand mit Vorlagen verwenden. Ist das erlaubt? –

Antwort

2

Sie müssten die Funktion void f() überladen, um den Manager-Datentyp zu verarbeiten.

Aber es wäre nur für Manager-Datentypen und keine der vom Manager abgeleiteten Klassen genau.

Wenn Sie eine Funktion erstellen möchten, um alle für die Mitarbeiterklasse zu steuern und Basisklassenzeiger für den Zugriff auf abgeleitete Elemente zu verwenden, müssen Sie das Schlüsselwort virtual verwenden. Es ist nur eine Voraussetzung von C++. (Ich bin mir sicher, dass es andere Möglichkeiten gibt, denn C++ ist extrem flexibel, aber sie sind sehr kompliziert und benötigen Zeit und zusätzlichen Code.)

Sie müssten jedoch nur 'virtual' in die Basisklasse eingeben, obwohl das als schlechte Praxis gilt. Wie so:

class Employee{ 
public: 
    virtual void what(){ 
     cout<<"Employee"<<endl; 
    } 
}; 

class Secretary:public Employee{ 
public: 
    void what(){ /*Still inherits 'virtual' without typing it.*/ 
     cout<<"Secretary"<<endl; 
    } 
}; 
3

Ok, hier eine völlig erfundene Methode, die nicht virtual durch den Kommentar von @Stephen inspirierte Anspruch nimmt - es speichert nur den Text in der Basisklasse, so dass, wenn die Funktion f Scheiben die Klasse Die Daten sind noch da.

#include<iostream> 
using namespace std; 
class Employee{ 
public: 
    std::string name; 
    Employee(std::string name = "Employee"):name(name){} 
    void what(){ 
     cout<<name<<endl; 
    } 
}; 
class Secretary:public Employee{ 
    public: 
    Secretary(std::string name = "Secretary"):Employee(name){} 
}; 
class Manager:public Employee{ 
    public: 
    Manager(std::string name = "Manager"):Employee(name){} 
}; 
class Director:public Manager{ 
    public: 
    Director(std::string name = "Director"):Manager(name){} 
}; 
void f(Employee*); 
int main(){ 
    Employee a; 
    Manager b; 
    Director c; 
    Secretary d; 
    f(&a); 
    f(&b); 
    f(&c); 
    f(&d); 
    return 1; 
} 
void f(Employee *a){ 
    a->what(); 
} 
+1

'f' schneidet nicht –

+0

Dies ist, was ich im Sinn hatte. Ich weiß nicht, warum er nicht virtuell sein wollte – Stephen

2

Eine Option ist:

template<typename T> 
void f(T *a) { a->what(); } 
Verwandte Themen