2

Where can I find some documentation for how we can initialize an object using list. Like the following?

class TestClass {
public:
    int a;
    int b;
};

Then initialize an object:

TestClass obj = TestClass{ 1, 2};
    cout << obj.a << " " << obj.b << endl;

I only found this page.

It seems it is method (2), but nothing is mentioned that what are the rules. For example, a,b,... must be public? I tried if add a private int c after them it does not work. For struct, I understand, my question is about class.

Russia Must Remove Putin
  • 374,368
  • 89
  • 403
  • 331
Mohammad Roohitavaf
  • 439
  • 2
  • 6
  • 15
  • 9
    struct, class, same thing. – juanchopanza Jun 28 '17 at 21:23
  • The only mayor difference between class and struct in c++ is that class uses private and struct uses public member access by default. – Tracer Jun 28 '17 at 21:32
  • I'm not sure what you mean with "initialize an object with list". Do you mean the std::list object? If your question is just how to initialize an object, you can create an object on the stack using `TestClass obj(1,2);` in your example. If you want to create it on the heap you can use `TestClass* obj = new TestClass(1,2);`. Don't forget to `delete obj;` when you are done using the object. – wuppie367 Jun 28 '17 at 21:37
  • 4
    it is aggregate initialization, not list initialization. I found it here : http://en.cppreference.com/w/cpp/language/aggregate_initialization Thanks – Mohammad Roohitavaf Jun 28 '17 at 21:38
  • Also keep an eye out for the term "Uniform Initialization" – user4581301 Jun 28 '17 at 21:51
  • @wuppie367 errm... [no](http://ideone.com/BQAcxT), not unless you provide the appropriate constructor – 463035818_is_not_an_ai Jun 28 '17 at 21:52
  • @MohammadRoohitavaf it is list initialization; the aggregate initialization is a possible subset of list initialization behaviour – M.M Jun 29 '17 at 22:36

2 Answers2

0

So what I've found is that you can initialize anything with that style in C++, as long as that thing is an 'aggregate'. Now! What is an aggregate?? Well that kind of depends upon what C++ standard - C++11, C++14, etc... - are we talking about. This is discussed eloquently in the answer to C++11 aggregate initialization for classes with non-static member initializers. I really hope this helps.

Salar Khan
  • 457
  • 3
  • 13
0

First, consider basic construction. It sounds like you just want to create a new TestClass and specify its initial values on-the-fly.

You can do this by using a constructor:

/**
 * TestClass.hpp
 */
class TestClass
{
public:
    int a;
    int b;

    TestClass(int aInitial, int bInitial);
};

/**
 * TestClass.cpp
 */
TestClass::TestClass(int aInitial, int bInitial)
: a(aInitial),
  b(bInitial)
{

}

// ... which is the same as...
TestClass::TestClass(int aInitial, int bInitial)
{
    this->a = aInitial;
    this->b = bInitial;
}

/**
 * SomewhereElse.cpp
 */
...
TestClass foobar(1, 2);
std::cout << foobar.a << std::endl; // 1
std::cout << foobar.b << std::endl; // 2
...

But let's assume you already considered that and you actually do need to use list initialization. The answer is actually on that page you mentioned, let's expand on it.

When you want to write something like this with a custom class...

TestClass foobar = { 1, 2 };

It requires some manual work first. There's no magic that will automatically assign the 0th index to your first member and the 1st index to your second member.

The compiler requires an assignment operator or constructor that accepts an std::initializer_list:

/**
 * TestClass.hpp
 */
class TestClass
{
public:
    int a;
    int b;

    TestClass(std::initializer_list<int> list); 
};

/**
 * TestClass.cpp
 */
TestClass::TestClass(std::initializer_list<int> list)
{
    if (list.size() != 2) {
        // Throw an error or set some defaults
    }

    int i = 0;
    for (int value : list) {
        if (i == 0) {
            this->a = value;
        } else {
            this->b = value;
        }

        i++;
    }
}

This will do what you're expecting it to do. But that constructor is pretty funky, isn't it? We have to do that weird for loop because std::initializer_list doesn't offer indexed access to its values (In other words, you can't do list[0] or list[1]).

You can make this easier to read by accepting a std::vector (or another kind of container like std::array, std::list, so on) in the constructor.

This works because an std::initializer_list is accepted as a constructor in those containers, and an implicit conversion can be performed:

/**
 * TestClass.hpp
 */
class TestClass
{
    int a;
    int b;

    TestClass(std::vector<int> values);
};

/**
 * TestClass.cpp
 */
TestClass::TestClass(std::vector<int> values)
{
    if (values.size() != 2) {
        // Throw an error or set some defaults
    }

    this->a = values[0];
    this->b = values[1];
}
Litty
  • 1,856
  • 1
  • 16
  • 35