エラー:非クラス型の '..'のメンバー '..'のリクエスト


439

2つのコンストラクターを持つクラスがあります。1つは引数を取らず、もう1つは引数を取ります。

1つの引数を取るコンストラクターを使用してオブジェクトを作成すると、期待どおりに機能します。ただし、引数を取らないコンストラクタを使用してオブジェクトを作成すると、エラーが発生します。

たとえば、このコードをコンパイルすると(g ++ 4.0.1を使用)...

class Foo
{
  public:
    Foo() {};
    Foo(int a) {};
    void bar() {};
};

int main()
{
  // this works...
  Foo foo1(1);
  foo1.bar();

  // this does not...
  Foo foo2();
  foo2.bar();

  return 0;
}

...次のエラーが発生します。

nonclass.cpp: In function int main(int, const char**)’:
nonclass.cpp:17: error: request for member bar in foo2’, which is of non-class type Foo ()()’

これはなぜですか、どのように機能させるのですか?


回答:


660
Foo foo2();

への変更

Foo foo2;

コンパイラが考えているため、エラーが発生します

Foo foo2()

名前が 'foo2'で戻り型が 'Foo'の関数宣言として。

しかし、その場合Foo foo2、に変更すると、コンパイラはエラーを表示する可能性があります " call of overloaded ‘Foo()’ is ambiguous"


6
コンパイラが考える理由がわかりません。メイン関数内の関数宣言の時点でFoo foo2()。
chaviaras michalis 2017年

どうやら私はそれを再び賛成することができないので、私は以前にこの回答に到達したことがあります!これがテキストの2番目の賛成票です...そして2番目の感謝です!
bigjosh 2017年

1
パラメータなしの関数宣言では、この使用が一貫性の観点から許可されるように、「void」パラメータを必須にする必要があります。私が間違っていなければ、K&R Cはvoidという用語を強制的に使用していました。
Rajesh

@Rajesh:空のパラメーターリストは必須ではありません。空のパラメーターリスト(指定されていないパラメーター)とは何か(ゼロのパラメーター)が異なるだけです。
Ben Voigt 2018

1
これは、c ++ 11で導入された統一{}初期化構文に切り替えるもう1つの良い理由です
Sumudu

41

参考までに…

実際にはコードの解決策ではありませんが、が指すクラスインスタンスのメソッドに誤ってアクセスすると、同じエラーメッセージが表示されましたmyPointerToClass

MyClass* myPointerToClass = new MyClass();
myPointerToClass.aMethodOfThatClass();

どこ

myPointerToClass->aMethodOfThatClass();

明らかに正しいでしょう。


11

知識ベースに追加すると、同じエラーが発生しました

if(class_iter->num == *int_iter)

IDEがclass_iterの正しいメンバーを私に与えたとしても。明らかに、問題は、"anything"::iterator呼び出されたメンバーがないnumため、参照を解除する必要があることです。これは次のように機能しません:

if(*class_iter->num == *int_iter)

...どうやら。私はこれを最終的にこれで解決しました:

if((*class_iter)->num == *int_iter)

これが、私が行った方法でこの質問に遭遇した人に役立つことを願っています。


8

パラメーター化されたコンストラクターを使用する予定がない場合、クラスオブジェクトをインスタンス化するために括弧は必要ありません。

Foo foo2を使用するだけ です。

それが動作します。


7

私は同様のエラーを抱えていましたが、コンパイラは引数なしのコンストラクタの呼び出しを誤解しているようです。変数宣言からかっこを削除することで、コードを次のように機能させました。

class Foo
{
  public:
    Foo() {};
    Foo(int a) {};
    void bar() {};
};

int main()
{
  // this works...
  Foo foo1(1);
  foo1.bar();

  // this does not...
  Foo foo2; // Without "()" 
  foo2.bar();

  return 0;
}

1
これは上記と同じ答えです
Greenonline 2015年

1
最も厄介なの解析は、それが標準であることであるとして、コンパイラの誤解そんなにない必要が曖昧さを防ぐために、関数宣言と関数宣言、かもしれない何かを解釈するようにコンパイラに。
ジャスティンタイム-モニカを2017年

(具体的には、との間[stmt.ambig/1][dcl.ambig.res/1]、あいまいな場合、宣言として解釈できるものはすべて、あいまいさを解決するための宣言であると明示的に規定されています。)
Justin Time-Monica

2

そのエラーメッセージが表示され、

Foo foo(Bar());

基本的に、一時的なBarオブジェクトをFooコンストラクターに渡そうとしていました。コンパイラがこれを次のように翻訳していたことが判明

Foo foo(Bar(*)());

つまり、名前がfooであり、引数を取るFooを返す関数宣言、つまり、引数が0のBarを返す関数ポインターです。このような一時的なものを渡すときBar{}Bar()、あいまいさをなくすために使用するよりも良いでしょう。


0

パラメータなしで新しいサブスタンスを宣言したい場合(オブジェクトにデフォルトのパラメータがあることを知っている場合)は記述しないでください

 type substance1();

だが

 type substance;

0

確かにこのエラーのコーナーケースですが、割り当てをオーバーロードしようとすると、別の状況で受け取りましたoperator=。これは少し不可解なIMOでした(g ++ 8.1.1以降)。

#include <cstdint>

enum DataType
{
  DT_INT32,
  DT_FLOAT
};

struct PrimitiveData
{
  union MyData
  {
    int32_t i;
    float f;
  } data;

  enum DataType dt;

  template<typename T>
  void operator=(T data)
  {
    switch(dt)
    {
      case DT_INT32:
      {
        data.i = data;
        break;
      }
      case DT_FLOAT:
      {
        data.f = data;
        break;
      }
      default:
      {
        break;
      }
    }
  }
};

int main()
{
  struct PrimitiveData pd;
  pd.dt = DT_FLOAT;
  pd = 3.4f;

  return 0;
}

2つの「同一の」エラーを受け取った

error: request for member i [and 'f'] in data’, which is of non-class type float

(等価エラーがclangあります。 error: member reference base type 'float' is not a structure or union

data.i = data;data.f = data;。コンパイラがローカル変数名 'data'と私のメンバー変数を混同していたことがわかりましたdata。これをvoid operator=(T newData)とに変更するとdata.i = newData;data.f = newData;エラーはなくなりました。


0

@MykolaGolubyevはすでに素晴らしい説明を行っています。私はこのようなことをするための解決策を探していましたMyClass obj ( MyAnotherClass() )が、コンパイラはそれを関数宣言として解釈していました。

C ++ 11にはbraced-init-listがあります。これを使用して、次のようなことができます

Temp t{String()};

ただし、これ:

Temp t(String());

tタイプと見なしてコンパイルエラーをスローしますTemp(String (*)())

#include <iostream>

class String {
public:
    String(const char* str): ptr(str)
    {
        std::cout << "Constructor: " << str << std::endl;
    }
    String(void): ptr(nullptr)
    {
        std::cout << "Constructor" << std::endl;
    }
    virtual ~String(void)
    {
        std::cout << "Destructor" << std::endl;
    }

private:
    const char *ptr;
};

class Temp {
public:
    Temp(String in): str(in)
    {
        std::cout << "Temp Constructor" << std::endl;
    }

    Temp(): str(String("hello"))
    {
        std::cout << "Temp Constructor: 2" << std::endl;
    }
    virtual ~Temp(void)
    {
        std::cout << "Temp Destructor" << std::endl;
    }

    virtual String get_str()
    {
        return str;
    }

private:
    String str;
};

int main(void)
{
    Temp t{String()}; // Compiles Success!
    // Temp t(String()); // Doesn't compile. Considers "t" as of type: Temp(String (*)())
    t.get_str(); // dummy statement just to check if we are able to access the member
    return 0;
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.