hata: '..' öğesindeki '..' öğesindeki sınıf olmayan türden istek


440

İki yapıcılı bir sınıfım var, biri argüman almıyor, diğeri ise bir argüman alıyor.

Bir argüman alan yapıcıyı kullanarak nesne oluşturmak beklendiği gibi çalışır. Ancak, hiçbir bağımsız değişken almayan yapıcı kullanarak nesneler oluşturursam, bir hata alıyorum.

Örneğin, bu kodu derlersem (g ++ 4.0.1 kullanarak) ...

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

... aşağıdaki hatayı alıyorum:

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

Bu neden ve nasıl çalıştırabilirim?


Yanıtlar:


661
Foo foo2();

değişmek

Foo foo2;

Hatayı alıyorsunuz çünkü derleyici düşünüyor

Foo foo2()

'foo2' adında işlev beyanı ve 'Foo' dönüş türü ile.

Ancak bu durumda Foo foo2, değiştirirsek derleyici hatayı gösterebilir " call of overloaded ‘Foo()’ is ambiguous".


6
Derleyicinin neden düşündüğünü anlamıyorum: Foo foo2 () işlev beyannamesi itibariyle, ana fonksiyon içinde.
chaviaras michalis

Görünüşe göre tekrar cevap veremediğim için bu cevaba indim! İşte bir metin 2. upvote ... ve 2. teşekkürler!
bigjosh

1
Parametresiz işlev bildirimi, "void" parametresini zorunlu kılacak, böylece bu kullanıma tutarlılık açısından izin verilecekti. Eğer yanılmıyorsam, K&R C zorunlu boşluk terimi kullanıyordu.
Rajesh

@Rajesh: Bir geçersiz parametre listesi zorunlu değildir, sadece boş bir parametre listesinden (belirtilmemiş parametreler) farklı bir şey (sıfır parametre) anlamına gelir.
Ben Voigt

1
bu, c ++ 11'de tanıtılan tekdüzen {} başlatma sözdizimine geçmek için başka bir iyi nedendir
Sumudu

41

Sadece kayıt için..

Aslında kodunuz için bir çözüm değil, ancak myPointerToClassörneğin tarafından işaret edilen bir sınıf örneğinin yöntemine yanlış erişirken aynı hata iletisine sahiptim.

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

nerede

myPointerToClass->aMethodOfThatClass();

Açıkçası doğru olur.


11

Bilgi tabanına ek olarak, aynı hatayı aldım

if(class_iter->num == *int_iter)

IDE bana class_iter için doğru üyeleri verdi bile. Açıkçası, sorun şu "anything"::iteratoradlı bir üyesi yok , bu numyüzden onu dereference gerekir. Hangi böyle çalışmaz:

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

...görünüşe göre. Sonunda bununla çözdüm:

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

Umarım bu, bu soruyla karşılaşan birine yaptığım gibi yardımcı olur.


8

Parametreli bir kurucu kullanmak istemediğinizde bir sınıf nesnesini başlatmak için parantez gerekmez.

Sadece Foo foo2 kullanın ;

Çalışacak.


7

Benzer bir hata yaşıyordum, derleyici argüman olmadan yapıcı çağrısını yanlış anlıyor gibi görünüyor. Ben kodunuzda böyle bir şey, değişken bildiriminden parantez kaldırarak işe yaradı:

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
En can sıkıcı ayrıştırma standart olmasıdır olarak, o kadar ki derleyici yanlış değil gerektirir belirsizliği önlemek için bir işlev bildirimi gibi bir işlev bildirimi olabilir şey, yorumlamak derleyici.
Justin Time - Monica'yı

(Özellikle, standart arasında [stmt.ambig/1]ve [dcl.ambig.res/1]açıkça, belirsizlik durumunda, bir belirsizlik olarak yorumlanabilecek her şeyin, bu belirsizliği gidermek için bir bildirim olduğunu ifade eder.)
Justin Time - Monica

2

Bu hata mesajını aldığım ve

Foo foo(Bar());

ve temelde geçici bir Bar nesnesini Foo yapıcısına aktarmaya çalışıyordu. Derleyicinin bunu

Foo foo(Bar(*)());

diğer bir deyişle, adı bağımsız değişken olan bir Foo döndüren foo olan bir işlev bildirimi - 0 bağımsız değişkeni olan bir Bar döndüren bir işlev işaretçisi. Bu gibi geçicilerden geçerken, belirsizliği ortadan kaldırmak Bar{}yerine kullanmak daha iyidir Bar().


0

Parametresiz (nesnenin varsayılan parametreleri olduğunu bilerek) yeni bir madde bildirmek istiyorsanız, yazma

 type substance1();

fakat

 type substance;

0

Kesinlikle bu hata için bir köşe durumu, ancak ödevi aşırı yüklemeye çalışırken farklı bir durumda aldım operator=. Biraz şifreli IMO'ydu (g ++ 8.1.1'den).

#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 "özdeş" hata aldım

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

(Eşdeğer bir hata clangolduğu: error: member reference base type 'float' is not a structure or union)

çizgiler için data.i = data;ve data.f = data;. Derleyicinin yerel değişken adı 'data' ve üye değişkenimi karıştırdığı ortaya çıktı data. Ben bu değiştiğinde void operator=(T newData)ve data.i = newData;, data.f = newData;hata gitti.


0

@MykolaGolubyev zaten harika bir açıklama yaptı. Böyle bir şey yapmak için bir çözüm arıyordum MyClass obj ( MyAnotherClass() )ama derleyici bunu bir fonksiyon bildirimi olarak yorumluyordu.

C ++ 11 hazır listeye sahip . Bunu kullanarak böyle bir şey yapabiliriz

Temp t{String()};

Ama, bu:

Temp t(String());

o gördüğü derleme hatası atar ttürü itibarıyla 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;
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.