fout: verzoek voor lid ‘..’ in ‘..’ dat van het type niet-klasse is

Ik heb een klasse met twee constructors, een die geen argumenten kan en een die maar één argument kan.

Het maken van objecten met behulp van de constructor waaraan één argument moet voldoen, werkt zoals verwacht. Als ik echter objecten maak met behulp van de constructor die geen argumenten nodig heeft, krijg ik een foutmelding.

Als ik deze code bijvoorbeeld compileer (met 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;
}

… Ik krijg de volgende foutmelding:

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

Waarom is dit en hoe zorg ik ervoor dat het werkt?


Antwoord 1, autoriteit 100%

Foo foo2();

wijzig in

Foo foo2;

Je krijgt de foutmelding omdat de compiler denkt aan

Foo foo2()

vanaf functiedeclaratie met de naam ‘foo2’ en het retourtype ‘Foo’.

Maar in dat geval Als we veranderen naar Foo foo2, kan de compiler de fout " call of overloaded ‘Foo()’ is ambiguous"tonen.


Antwoord 2, autoriteit 6%

Voor de goede orde..

Het is eigenlijk geen oplossing voor uw code, maar ik kreeg dezelfde foutmelding bij het onjuist openen van de methode van een klasse-instantie waarnaar wordt verwezen door myPointerToClass, bijvoorbeeld

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

waar

myPointerToClass->aMethodOfThatClass();

zou uiteraard correct zijn.


Antwoord 3

Toen ik de kennisbank aanvulde, kreeg ik dezelfde fout voor

if(class_iter->num == *int_iter)

Ook al gaf de IDE me de juiste leden voor class_iter. Het probleem is duidelijk dat "anything"::iteratorgeen lid heeft met de naam num, dus ik moet de verwijzing ernaar verwijderen. Wat niet zo werkt:

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

…blijkbaar. Uiteindelijk heb ik het hiermee opgelost:

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

Ik hoop dat dit iemand helpt die deze vraag op dezelfde manier tegenkomt als ik.


Antwoord 4

Een haakje is niet vereist om een klasseobject te instantiëren als u niet van plan bent een geparametriseerde constructor te gebruiken.

Gebruik gewoon Foo foo2;

Het zal werken.


Antwoord 5

Ik had een soortgelijke fout, het lijkt erop dat de compiler de aanroep van de constructor zonder argumenten verkeerd heeft begrepen. Ik heb het laten werken door de haakjes uit de variabele declaratie te verwijderen, in je code ongeveer als volgt:

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;
}

Antwoord 6

Ik kwam een geval tegen waarin ik die foutmelding kreeg en had

Foo foo(Bar());

en probeerde in feite een tijdelijk Bar-object door te geven aan de Foo-constructor. Blijkt dat de compiler dit vertaalde naar

Foo foo(Bar(*)());

dat wil zeggen een functiedeclaratie waarvan de naam foo is en die een Foo retourneert die een argument opneemt — een functieaanwijzer die een Bar retourneert met 0 argumenten. Als u op deze manier tijdelijke gegevens doorgeeft, kunt u beter Bar{}gebruiken in plaats van Bar()om dubbelzinnigheid te voorkomen.


Antwoord 7

Als u een nieuwe stof zonder parameter wilt declareren (wetend dat het object standaardparameters heeft), schrijf dan niet

type substance1();

maar

type substance;

Antwoord 8

Zeker een hoekgeval voor deze fout, maar ik ontving het in een andere situatie, toen ik probeerde de opdracht operator=te overbelasten. Het was een beetje cryptisch IMO (van 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;
}

Ik heb 2 “identieke” fouten ontvangen

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

(De equivalente fout voor clangis:
error: member reference base type 'float' is not a structure or union)

voor de regels data.i = data;en data.f = data;. Blijkt dat de compiler de lokale variabelenaam ‘data’ en mijn lidvariabele datadoor elkaar haalde. Toen ik dit veranderde in void operator=(T newData)en data.i = newData;, data.f = newData;, de fout ging weg.


Antwoord 9

@MykolaGolubyev heeft al een prachtige uitleg gegeven. Ik was op zoek naar een oplossing om zoiets als dit te doen MyClass obj ( MyAnotherClass() )maar de compiler interpreteerde het als een functiedeclaratie.

C++11 heeft braced-init-list. Hiermee kunnen we zoiets als dit doen

Temp t{String()};

Echter, dit:

Temp t(String());

geeft een compilatiefout omdat het tvan het type Temp(String (*)())beschouwt.

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

Other episodes