Reputation: 144
I'm not an expert C++ developer, I'm not sure if is it possible to do what I want.
I have a template class like:
template < typename T >
class table
{
public
table ( AnotherClassPtr* handler, int s);
table<T>& operator<<(const T& table);
table<T>& operator>>( T& table);
...
}
I have a standard class. In this class I would like to create some members that are table
objects. es:
class A{
public:
...
AnotherClassPtr* pointer;
table<aCertainStruct> myTable;
...
}
It does not work because I miss the default constructor of table
. But I can't make a default constructor because I need to pass to the table
class a pointer to AnotherClassPtr
which is created in the constructor of class A just before where i would like to call the constructor I defined for table
. es:
//inside the constructor of the A class.
....
pointer= getAnotherClassPtr();
table<aCertainStruct> myTable ( pointer, 42);
...
[an attempt] The stuff below compile but it does not work as I expected. Infact if I try to call some funcions of the class table it does not work.
class A{
public:
...
AnotherClassPtr* pointer;
table<aCertainStruct> myTable ( AnotherClassPtr*, unsigned int)
...
}
// in the constructor of the A class
....
pointer= getAnotherClassPtr();
table<aCertainStruct> myTable ( pointer, 42);
...
Q: is it possible to create a template class variable as member of a non template class?
Or in other workds: is it possible to define a table
member in the A
class declaration and then define the table object calling my user defined constructor inside the A
constructor?
I'm sorry for my bad english, is not my native language, I hope the problem is clear.
thanks in advance.
Upvotes: 0
Views: 892
Reputation: 72473
In simple cases like this, you can use the member initializer syntax rather than assigning to (already initialized) members.
class A
{
public:
A() :
pointer(getAnotherClassPtr()),
myTable(pointer, 42)
{}
//...
// pointer must come before myTable!
AnotherClassPtr* pointer;
table<aCertainStruct> mytable;
};
As noted in the class comment, this wouldn't work if mytable
were declared before pointer
in the class definition. The order class members are initialized always depends on the order the class declared them, not the order of the constructor's member initializer list. Also, if getAnotherClassPtr
is a member of A
, make sure it's either marked static
or it doesn't use any other members of A
declared before pointer
, for the same reason.
If you have other reasons to want class members declared in a certain order, or if the initialization logic is more complicated in other ways, a more general solution to this sort of issue is to use a private helper struct and delegate to a private constructor:
class A
{
private:
struct InitHelper;
public:
A() : A(InitHelper()) {}
// ...
// Now member order doesn't matter.
table<aCertainStruct> mytable;
AnotherClassPtr* pointer;
// ...
private:
explicit A(InitHelper&& helper);
};
struct A::InitHelper
{
AnotherClassPtr* pointer;
unsigned int mytable_arg2;
InitHelper();
};
inline A::InitHelper::InitHelper()
{
// Actual logic here!
// ...
pointer = getAnotherClassPtr();
mytable_arg2 = 42;
// ...
}
inline A::A(InitHelper&& helper) :
mytable_arg2(helper.pointer, helper.mytable_arg2),
pointer(helper.pointer)
{}
Upvotes: 1
Reputation: 409472
That's why there exists constructor initializer lists:
class A{
public:
A()
: pointer(getAnotherClassPtr()), myTable(pointer, some_value)
{}
...
AnotherClassPtr* pointer;
table<aCertainStruct> myTable;
...
};
This will initialize and "call" the parameterised constructor of table
, instead of the default constructor.
These days with a relatively modern compiler, you should also be able to do something similar to what you want in the second attempt of the A
class, but you have to use "assignment" syntax for the initialization, or curly-braces {}
instead of parentheses ()
(since parentheses are for member functions):
table<aCertainStruct> myTable{pointer, some_value};
This of course requires that pointer
is initialized first.
Upvotes: 1