Search code examples
c++c++11constructorxcode8list-initialization

Member Initialization in overloaded constructor


I have a basic semantic related doubt that I couldn't able to get clarified. Before stating the problem I will write down the minimum code to explain it clearly.

In Constants.hpp

#pragma once
enum class OpenglESVersion{
    OES1,
    OES2
};

In Cone.hpp, I have a enum member

OpenglESVersion esVersion;

Overloaded constructor definition in Cone.cpp that takes enum as parameter

Cone::Cone(const OpenglESVersion version) : rotationAngle(0), scale(1), esVersion(version) {}

Now in My RenderingEngine.cpp when i instantiate the Cone object:

Cone cone(OpenglESVersion::OES2);

I get syntax error:

No type named 'OES2' in 'OpenglESVersion'

Now If I update my object instantiaition to:

Cone cone{OpenglESVersion::OES2};

Now it works.

My complier is libc++[LLVM c++ standard library with c++ 11 support] ,and the dialect is c++11[-std=c++11] I am using XCode.

Now coming to my doubt: I went through resources to clarify the concept. In past I had use pre c++11 version in school following Bjarne's C++ programming Book which was printed in 2008, so that's why I didn't find this "curly" initialization syntax on the book for c++11 came out later.

I tried google and wasn't sure of what keyword to search but later the most common subject name pointed to "list initialization". Almost every resource covered on the advantage of this new syntax in c++11 but I never got clarified on why normal round bracket is treated as syntax error because there are many resource out there where example shows using rounder bracket too with combination of curly braces while explaining the difference but they were using examples of primitive types like:

int x(4);
int x{4};

So again this was not clarifying the concept for me. Now I am here to know or have some guidance to appropriate link or resource that explain my doubt.

  • Has my compiler made that round bracket intialization syntax obsolete?
  • It's not obsolete but was never supported in c++?
  • I have declared and defined the overloaded constructor wrongly?
  • Is initialiation of member not supported via round bracket syntax? and why?

EDIT: This happens for any overloaded version, lets say int parameter overloaded version of constructor.

Cone::Cone(const int fooVariable) : fooMember(fooVariable){}

Only code works is:

Cone cone{8};

I get

Expected parameter declarator, Expected ')'

for Cone cone(8);

This behaviour doesn't happen if for curiosity I instantiate inside the member function of Cone class itself like the compiler doesn't thow any syntax or some error:

void Cone::Test(){
    Cone cone(OpenglESVersion::OES2);
}

EDIT UPDATE 2: I think I have another test case which should definitely narrow down. So here is the pattern:

class RenderingEngine
{
private:
    Cone cone(OpenglESVersion::OES2);
};

So I am declaring and instantiating the Cone object as a member of RenderingEngine class. So could it be this that is causing my issue? Because If I do

Cone cone(OpenglESVersion::OES2);

inside any member function of RenderingEngine/Outside class implementation then it works. So There must be some basic rule that I am violating on what and how non-primitive member variable can be declared and instantiated.


Solution

  • Member initialization has been introduced in C++11.

    Parenthesis are not supported to avoid the most vexing parse, so you can use {..} or = syntax:

    class RenderingEngine
    {
    private:
        Cone cone{OpenglESVersion::OES2};
    };
    

    or

    class RenderingEngine
    {
    private:
        Cone cone = Cone(OpenglESVersion::OES2); // With =, you can use parent on right side
    };