2011-10-14 10 views

答えて

34

あなたは、あなたがこれを書くと、メンバー関数size()のアドレスを取得するとします:

auto address = &demo::size; 

しかし、それは、メンバーデータのアドレスであることが非常によくなる可能性がありsizeとしてよくあいまいな状況。したがって、言語仕様では許可されていません。

これは、C++委員会が解決策を思いつくことは不可能だと言っているわけではありませんが、大きな利益はないと思います。したがって、スタンダードは物事を単純に保つために単にそれを許さなかった。

また、メンバーのデータとメンバー関数の違いはあまり区別できるなり視覚 1はとしてメンバ関数size()を宣言している場合:

typedef void fun_type(); 

struct demo 
{ 
    fun_type size; //It looks like a member-data, but it's a member-function 
}; 

void demo::size() //define the member function 
{ 
    std::cout << "It is crazy!" << std::endl; 
} 

int main() 
{ 
    demo d; 
    d.size(); //call the function! 
} 

出力:

それはクレイジーです!上述したように、我々はメンバ関数を実装することができれば、それも、あなたが同じ名などで、他のメンバーを追加することはできません肉眼ではあまりにも明白になり、今http://ideone.com/ZjwyJ

は、オンラインデモを参照してください。

struct demo 
{ 
    fun_type size; 
    int  size; //error - choose a different name for the member! 
}; 

待機まだ完全には終わっていませんが、ストーリーはまだ完成していません。私がここに追加する必要があるものはあまり明白ではありません。

:各メンバーが 異なるタイプの 機能あるので、あなたは、それらを定義することができるよう

typedef void fun_type0(); 
typedef void fun_type1(int a); 
typedef void fun_type2(int a, int b); 

struct demo 
{ 
    fun_type0 member; //ok 
    fun_type1 member; //ok 
    fun_type2 member; //ok 
}; 

これは、完全に有効なコードです:あなた同じ名前の複数のメンバーを追加することができます

void demo::member() 
{ 
    std::cout << "member()" << std::endl; 
} 
void demo::member(int a) 
{ 
    std::cout << "member(" << a << ")" << std::endl; 
} 
void demo::member(int a, int b) 
{ 
    std::cout << "member(" << a << ", "<< b << ")" << std::endl; 
} 

テストコード:

int main() 
{ 
    demo d; 
    d.member(); 
    d.member(10); 
    d.member(200,300); 
} 

出力:

member() 
member(10) 
member(200, 300) 

オンラインデモ:http://ideone.com/OM97Q


結論...

あなたがいる限り、彼らはの機能していると、同じ名前のメンバーを追加することができます異なるタイプです。これは、メンバ関数オーバーロード(または単純な関数のオーバーロード)と呼ばれる機能によってを有効にしました。です。

1.残念なことに、この言語ではメンバデータのメンバデータオーバーロードと同様の機能は提供されません。また、クロスメンバオーバーロード(メンバデータとメンバ関数の質問に同じ名前の—がある)。

ここで質問が自然に発生します:原因はありませんあいまいさ問題?はい、彼らがやります。しかし注目すべき点は、C++委員会がこの曖昧さ問題を解決するための解決策を思いつきました。なぜなら、関数オーバーロードの場合にそうした大きな利益を見たからです。

しかし、委員会は解決策を考え出していないので、疑問が残っています。前にも述べたように、大きな利点は見られませんでした。また、"C++委員会が解決策を思いついた" ソリューション標準化であったというだけで、コンパイラがどのように解決できるかを知っていたということです。さあ。

+0

あいまいさは本当に答えではありません。 'demo :: size'がオーバーロードされた関数だった場合とどう違うのでしょうか? – tenfour

+1

@tenfour:あなたはポイントを完全に見逃しました。オーバーロードされた関数についてもあいまいさ*がありましたが、C++委員会はこのあいまいさの問題を解決するための解決策を思いつきました。しかし、委員会が解決策を見出せなかったので、疑問のこのケースはあいまいである。そして、「C++委員会が解決策を出した」*と言ったとき、私は解決策が標準化されているわけではなく、コンパイラがどのように解決できるか、ソリューションがどれほど複雑であるかを知っていたということです。 – Nawaz

+0

私はポイントを得ましたが、それは[この質問](http://stackoverflow.com/questions/4331837/why-cant-functions-be-overloaded-by-return-type)に似ているようです曖昧さですが、より具体的な理由は、委員会が外部の文脈に依存しない関数呼び出しをしたいということです。私はこの質問に同様に詳細な答えがあるのだろうかと思います。 (またはこれは答えかもしれません) – tenfour

6

あなたのクラスでsizeを使用すると、コンパイラは何をすべきか分からないからです。これは、int-data-memberのいずれかでも、関数ポインタでもかまいません。だから、コンパイラは(おそらく最高のそれは視覚的にそれを説明するかもしれない)の例としては親切

6

両方を区切ることができません。

class Size { 
     std::size_t size_; 
    public: 
     Size(std::size_t s = std::size_t()) : size_(s){} 
     std::size_t operator()() const { 
      return size_; 
     } 
     void operator()(std::size_t s) { 
      size_ = s; 
     }   
}; 

class Demo { 
    public: 
     Size size; 
}; 

int main() { 
    Demo d; 
    d.size(10); 
    std::size_t size = d.size(); 
    return 0; 
} 

基本的には変数も同様に呼び出し可能である可能性があります。したがって、コンパイラがあなたの意図を知る方法はありません。 もちろん、これは、同じスコープ内で識別子と同じ名前を持つことはできないことが言語によって定義されています。

+0

優れた例。 – UncleZeiv