简体   繁体   中英

C++ says expected identifier before numeric constant

class data
{
private:
    int ID;
    string address,name;
public:
    data(int i,string a,string n):ID(i),address(a),name(n){}
    friend class SetData;
};
class SetData
{
private:
    data obj(43,"185 Awan Market","Talha"); //this is where the error happens

public:
    void show()
    {
        cout<<"Name is: "<<obj.name<<endl;
        cout<<"Address is: "<<obj.address<<endl;
        cout<<"ID is: "<<obj.ID;
    }
};

C++03

It belongs in the constructor's mem-initializer:

class SetData
{
private:
    data obj;

public:
    SetData() : obj(43,"185 Awan Market","Talha")
    {
    }
    // Rest goes here...
};

C++11

You must use a brace or equal initializer.

// Fine
data obj{43,"185 Awan Market","Talha"};
// Fine, too
data obj = data(43,"185 Awan Market","Talha"); //this is where the error happens

For why parentheses are not allowed, see the Non-static data member initializers proposal. Scroll down to "An issue raised in Kona regarding scope of identifiers"

The motivation for class-scope lookup is that we'd like to be able to put anything in a non-static data member's initializer that we could put in a mem-initializer without significantly changing the semantics (modulo direct initialization vs. copy initialization):

 int x(); struct S { int i; S() : i(x()) {} // currently well-formed, uses S::x() // ... static int x(); }; struct T { int i = x(); // should use T::x(), ::x() would be a surprise // ... static int x(); }; 

Unfortunately, this makes initializers of the “( expression-list )” form ambiguous at the time that the declaration is being parsed:

 struct S { int i(x); // data member with initializer // ... static int x; }; struct T { int i(x); // member function declaration // ... typedef int x; }; 

One possible solution is to rely on the existing rule that, if a declaration could be an object or a function, then it's a function:

 struct S { int i(j); // ill-formed...parsed as a member function, // type j looked up but not found // ... static int j; }; 

A similar solution would be to apply another existing rule, currently used only in templates, that if T could be a type or something else, then it's something else; and we can use “typename” if we really mean a type: Essentially

 struct S { int i(x); // unabmiguously a data member int j(typename y); // unabmiguously a member function }; 

Both of those solutions introduce subtleties that are likely to be misunderstood by many users (as evidenced by the many questions on comp.lang.c++ about why “int i();” at block scope doesn't declare a default-initialized int).

The solution proposed in this paper is to allow only initializers of the “= initializer-clause” and “{ initializer-list }” forms. That solves the ambiguity problem in most cases, for example:

 HashingFunction hash_algorithm{"MD5"}; 

Initializing non-static data members in such a way is not allowed. You should rather be using a brace-or-equal initializer

class SetData
{
private:
    // data obj = {43,"185 Awan Market","Talha"}; is also valid
    data obj{43,"185 Awan Market","Talha"};

Cfr. non-static data members initialization

Alternative solution: constructor initializer list

class SetData
{
private:
    data obj;

public:
    SetData() : obj(43,"185 Awan Market","Talha") {}

    void show() 
    ...
};

As to why parenthesis are not supported for non-static data members initialization, I recommend reading this post: Why C++11 in-class initializer cannot use parentheses?

You can't initialize objects inline like that, you have to do it in the constructors initializer list:

class SetData
{
private:
    data obj;

public:
    SetData() : obj(43,"185 Awan Market","Talha") {}
    ...
};

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM