2016-05-05 6 views
0

仮想キーなしで派生クラスのメンバー関数に到達する方法を教えてください。仮想キーワードを避ける方法

#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(); 
} 

"Employee"が常に出力されます。私は各オブジェクトのクラスの名前を印刷したい。 とa.what()はクラス名を正しく出力します。しかし、私はポインタとf(Employee *)関数をこの割り当てに使用する必要があります。

+1

あなたがそれを入力する内容に、各タイプに識別子を置くことができますが従業員= 1、マネージャー= 2、ディレクター= 3です。 「タグ付き発送」と呼ばれるものもあります。https://crazycpp.wordpress.com/2014/12/15/tutorial-on-tag-dispatching/ – xaxxon

+2

できません。仮想関数は**派生クラスが存在する唯一の理由です。仮想関数を使用すべきではないとあなたの任務は言いますか?もしそうなら、脱落する。 –

+3

テンプレートを使用して静的ディスパッチを使用できます。それは許されますか? –

答えて

2

Managerのデータ型を処理するには、void f()関数をオーバーロードする必要があります。

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

ただし、マネージャのデータ型は正確で、マネージャから派生したクラスはありません。

従業員クラスのすべてを統治する関数を作成し、派生メンバーにアクセスするためにベースクラスのポインタを使用する場合は、virtualキーワードを使用する必要があります。それは単なるC++の要件です。 (C++は非常に柔軟性があるので、他の方法があると確信していますが、非常に複雑で時間がかかり、余分なコードが必要です)

しかし、基本クラスに 'virtual'それは悪い習慣とみなされます。これと同じように:

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]を、ここで@Stephenによってコメントに触発virtualを使用しない完全に不自然な方法がある - それだけで、基本クラス内のテキストを格納するようにするとき、関数fスライスクラスデータはまだそこにあります。

#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'はスライスしません –

+0

これは私が気にしていたことです。私はなぜ彼が仮想を望んでいないのか分からない – Stephen

2

一つのオプションは次のとおりです。

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

あなたは4つのコピー書き出すの代わりに、テンプレートを使用することもできます。

template<typename T> 
void f(T *a) { a->what(); } 
関連する問題