559 Stimmen

Fehler: Anfrage nach Mitglied '..' in '..', das nicht vom Klassentyp ist

Ich habe eine Klasse mit zwei Konstruktoren, von denen einer keine Argumente und der andere ein Argument benötigt.

Das Erstellen von Objekten mit dem Konstruktor, der ein Argument benötigt, funktioniert wie erwartet. Wenn ich jedoch Objekte mit dem Konstruktor erstelle, der keine Argumente benötigt, erhalte ich einen Fehler.

Wenn ich zum Beispiel diesen Code kompiliere (mit 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;
}

... Ich erhalte den folgenden Fehler:

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 ()()’

Warum ist das so, und wie kann ich es schaffen?

4voto

solstice333 Punkte 3017

Ich hatte einen Fall, in dem ich diese Fehlermeldung erhielt und

Foo foo(Bar());

und hat im Grunde versucht, ein temporäres Bar-Objekt an den Foo-Konstruktor zu übergeben. Wie sich herausstellte, übersetzte der Compiler dies in

Foo foo(Bar(*)());

das heißt, eine Funktionsdeklaration mit dem Namen foo, die einen Foo zurückgibt, der ein Argument aufnimmt - einen Funktionszeiger, der einen Bar mit 0 Argumenten zurückgibt. Bei der Übergabe von Provisorien wie diesem, sollte man besser Bar{} anstelle von Bar() um Zweideutigkeiten zu beseitigen.

1voto

Mo el Punkte 1

Wenn Sie einen neuen Stoff ohne Parameter deklarieren wollen (weil Sie wissen, dass das Objekt Standardparameter hat), schreiben Sie nicht

 type substance1();

sondern

 type substance;

1voto

yano Punkte 4023

Sicherlich ein Eckfall für diesen Fehler, aber ich erhielt ihn in einer anderen Situation, als ich versuchte, die Zuweisung zu überladen operator= . Es war ein bisschen kryptisch IMO (von 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;
}

Ich habe 2 "identische" Fehler erhalten

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

(Der entsprechende Fehler für clang ist: error: member reference base type 'float' is not a structure or union )

für die Zeilen data.i = data; y data.f = data; . Es stellte sich heraus, dass der Compiler den Namen der lokalen Variable "data" und meine Mitgliedsvariable verwechselt hat data . Als ich dies änderte in void operator=(T newData) y data.i = newData; , data.f = newData; ist der Fehler verschwunden.

0voto

abhiarora Punkte 8673

@MykolaGolubyev hat bereits eine wunderbare Erklärung gegeben. Ich war auf der Suche nach einer Lösung, um etwas wie dies zu tun MyClass obj ( MyAnotherClass() ) aber der Compiler hat sie als Funktionsdeklaration interpretiert.

C++11 hat verankerte-init-Liste . Auf diese Weise können wir etwas wie folgt tun

Temp t{String()};

Doch dies:

Temp t(String());

wirft einen Kompilierungsfehler, da es die t ab dem Typ 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;
}

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X