Consider the following code:
#include <vector>
class A
{
public:
A(A&&); // somewhat expensive
static std::vector<A> make_As()
{
std::vector<A> result;
result.push_back(A(3));
result.push_back(A(4));
return result;
}
private:
A(int); // private constructor
};
Since A's move constructor is somewhat expensive (for whatever reason), I'd like to avoid calling it and use emplace_back() instead:
#include <vector>
class A
{
public:
A(A&&); // somewhat expensive
static std::vector<A> make_As()
{
std::vector<A> result;
result.emplace_back(3);
result.emplace_back(4);
return result;
}
private:
A(int); // private constructor
};
Unfortunately, with emplace_back(), the actual constructor call is done by something in the standard library, which is not privileged enough to be able to call A's private constructor.
I realize that there's probably little that can be done about this, but nonetheless I feel that since the calls to emplace_back() occur within a member of A, they ought to be able to call the private constructor.
Are there any workarounds for this?
The only thing I can think of is to add a friend-declaration to A, but the precise class that needs to be A's friend (that is, the class that actually tries to invoke the constructor) is implementation-specific (for example, for GCC it's __gnu_cxx::new_allocator<A>). EDIT: just realized that such a friend declaration will allow anyone to emplace_back() A's constructed with the private constructor into a container of A's, so it wouldn't really solve anything, I might as well make the constructor public at that point...
UPDATE: I should add that A's move constructor being expensive is not the only reason to avoid having to call it. It may be that A is not movable at all (nor copyable). That would not work with vector, of course, (because emplace_back() may have to reallocate the vector), but it would with deque, which also has a similar emplace_back() method but does not have to reallocate anything.
One possible workaround (or kludge) would be to use a helper class to hold the parameters to the private ctor of A (let's call this class EmplaceHelper). EmplaceHelper should also have a private ctor, and it should be in mutual friendship with A. Now all you need is a public ctor in A that takes this EmplaceHelper (via const-ref, probably), and use that with emplace_back(EmplaceHelper(...)).
Since EmplaceHelper can only be constructed by A, your public ctor is still effectively private.
It might even be possible to generalize this idea with a templated EmplaceHelper (possibly using std::tuple to hold the ctor parameters).
Edit: actually, it seems I overcomplicated this as a comment below from GManNickG gave me a simpler idea: add a private helper class (private_ctor_t in the example) that is just an empty class but since it is private it is only accessible by A. Modify A's constructor to include this private class as the first (or last) parameter (and make it public). The effect would be that only A could construct itself as if it had a private constructor, but this construction could be easily delegated now.
Like this:
#include <vector>
class A
{
private:
struct private_ctor_t {};
public:
A(private_ctor_t, int x) : A(x) // C++11 only, delegating constructor
{}
A(A&&) { /* somewhat expensive */ }
static std::vector<A> make_As()
{
std::vector<A> result;
result.emplace_back(private_ctor_t{}, 3);
result.emplace_back(private_ctor_t{}, 4);
return result;
}
private:
A(int) { /* private constructor */ }
};
If delegated constructors are not available, you can either factor out the common code for each version, or just get rid of A(int) altogether and only use the new version.
By the C++11 standard, all of the standard containers should use the allocator::construct method to do in-place construction. As such, you could simply make std::allocator a friend of A.
I suppose technically this function is allowed to delegate the actual construction call to something else. Personally, I think the spec should be a little more strict about enforcing exactly which objects call constructors and what can and cannot be delegated.
If such delegation occurs, or for whatever reason, you could provide your own allocator that forwards all calls to std::allocator except for construct. I don't suggest the latter, as many standard container implementations have special code for dealing with std::allocator that allows them to take up less space.
just realized that such a friend declaration will allow anyone to emplace_back() A's constructed with the private constructor into a container of A's, so it wouldn't really solve anything, I might as well make the constructor public at that point...
Then you're going to have to decide what's more important to you: in-place construction, or hiding privates. By it's very nature, in-place construction means that someone not in your code is doing the construction. Therefore, there's no way around it: some external code must be named a friend or the constructor must be public. In short, the constructor must be publicly accessible to whomever is delegated the construction.
Let's simplify a bit. The following fails to compile, because V has no access to A's private constructor.
struct V
{
E(int i)
{
// ...
auto a = A(i);
// ...
}
};
Going back to your code, V is just a simplification of vector, and V::E is just a simplification of what emplace_back does. vector doesn't have access to A's private constructor, and vector::emplace_back needs to call it.
Related
I know we can explicitly call the constructor of a class in C++ using scope resolution operator, i.e. className::className(). I was wondering where exactly would I need to make such a call.
You also sometimes explicitly use a constructor to build a temporary. For example, if you have some class with a constructor:
class Foo
{
Foo(char* c, int i);
};
and a function
void Bar(Foo foo);
but you don't have a Foo around, you could do
Bar(Foo("hello", 5));
This is like a cast. Indeed, if you have a constructor that takes only one parameter, the C++ compiler will use that constructor to perform implicit casts.
It is not legal to call a constructor on an already-existing object. That is, you cannot do
Foo foo;
foo.Foo(); // compile error!
no matter what you do. But you can invoke a constructor without allocating memory - that's what placement new is for.
char buffer[sizeof(Foo)]; // a bit of memory
Foo* foo = new(buffer) Foo(); // construct a Foo inside buffer
You give new some memory, and it constructs the object in that spot instead of allocating new memory. This usage is considered evil, and is rare in most types of code, but common in embedded and data structure code.
For example, std::vector::push_back uses this technique to invoke the copy constructor. That way, it only needs to do one copy, instead of creating an empty object and using the assignment operator.
Most often, in a child class constructor that require some parameters :
class BaseClass
{
public:
BaseClass( const std::string& name ) : m_name( name ) { }
const std::string& getName() const { return m_name; }
private:
const std::string m_name;
//...
};
class DerivedClass : public BaseClass
{
public:
DerivedClass( const std::string& name ) : BaseClass( name ) { }
// ...
};
class TestClass :
{
public:
TestClass( int testValue ); //...
};
class UniqueTestClass
: public BaseClass
, public TestClass
{
public:
UniqueTestClass()
: BaseClass( "UniqueTest" )
, TestClass( 42 )
{ }
// ...
};
... for example.
Other than that, I don't see the utility. I only did call the constructor in other code when I was too young to know what I was really doing...
I think the error message for compiler error C2585 gives the best reason why you would need to actually use the scope-resolution operator on the constructor, and it does in with Charlie's answer:
Converting from a class or structure type based on multiple inheritance. If the type inherits the same base class more than once, the conversion function or operator must use scope resolution (::) to specify which of the inherited classes to use in the conversion.
So imagine you have BaseClass, and BaseClassA and BaseClassB both inherit BaseClass, and then DerivedClass inherits both BaseClassA and BaseClassB.
If you are doing a conversion or operator overload to convert DerivedClass to a BaseClassA or BaseClassB, you will need to identify which constructor (I'm thinking something like a copy constructor, IIRC) to use in the conversion.
In general you do not call the constructor directly. The new operator calls it for you or a subclass calls the parent class' constructors. In C++, the base class is guarenteed to be fully constructed before the derived class' constructor starts.
The only time you would call a constructor directly is in the extremely rare case where you are managing memory without using new. And even then, you shouldn't do it. Instead you should use the placement form of operator new.
I don't think you would typically use that for the constructor, at least not in the way you're describing. You would, however, need it if you have two classes in different namespaces. For example, to specify the difference between these two made-up classes, Xml::Element and Chemistry::Element.
Usually, the name of the class is used with the scope resolution operator to call a function on an inherited class's parent. So, if you have a class Dog that inherits from Animal, and both of those classes define the function Eat() differently, there might be a case when you want to use the Animal version of eat on a Dog object called "someDog". My C++ syntax is a little rusty, but I think in that case you would say someDog.Animal::Eat().
There are valid use cases where you want to expose a classes constructors. If you wish to do your own memory management with an arena allocator for example, you'll need a two phase construction consisting of allocation and object initialization.
The approach I take is similar to that of many other languages. I simply put my construction code in well known public methods (Construct(), init(), something like that) and call them directly when needed.
You can create overloads of these methods that match your constructors; your regular constructors just call into them. Put big comments in the code to warn others that you are doing this so they don't add important construction code in the wrong place.
Remember that there is only one destructor method no matter which construction overload was used, so make your destructors robust to uninitialized members.
I recommend against trying to write initializers that can re-initialize. It's hard to tell the case where you are looking at an object that just has garbage in it because of uninitialized memory vs. actually holding real data.
The most difficult issue comes with classes that have virtual methods. In this case the compiler normally plugs in the vtable function table pointer as a hidden field at the start of the class. You can manually initialize this pointer, but you are basically depending on compiler specific behavior and it's likely to get your colleagues looking at you funny.
Placement new is broken in many respects; in the construction/destruction of arrays is one case so I tend not to use it.
Consider the following program.
template<class T>
double GetAverage(T tArray[], int nElements)
{
T tSum = T(); // tSum = 0
for (int nIndex = 0; nIndex < nElements; ++nIndex)
{
tSum += tArray[nIndex];
}
// Whatever type of T is, convert to double
return double(tSum) / nElements;
}
This will call a default constructor explicitly to initialize the variable.
I mostly work on system-level C++ projects that don't allow exceptions to be thrown, but RAII is (rightfully) strongly encouraged. Right now, we handle the lack of failing constructors using infamous tricks many C++ programmers are familiar with, like:
Trivial constructor followed by a call to bool init(Args...) to do the hard stuff
Real constructor followed by checking bool is_valid() const
Heap-allocating with static unique_ptr<MyType> create(Args...)
Of course, these all have drawbacks (heap allocation, invalid and "moved" states, etc).
My company is finally updating compilers and will allow glorious C++17 to be used. Since C++17 features std::optional<T> and, most importantly, mandatory copy elision, I was hoping I could greatly simplify all our classes into something that would look like this:
class MyType {
public:
static std::optional<MyType> create() {
// If any of the hard stuff fails, return std::nullopt
return std::optional<MyType>(std::in_place, 5, 'c');
}
~MyType() {
// Cleanup mArg0 and mArg1, which are always valid if the object exists
}
// ... class functionality ...
// Disable default constructor, move, and copy.
// None of these are needed because mandatory copy elision
// allows the static function above to return rvalue without
// copy or move operations
MyType() = delete;
MyType(const MyType&) = delete;
MyType(MyType&&) = delete;
MyType& operator=(const MyType&) = delete;
MyType& operator=(MyType&&) = delete;
private:
MyType(ArgT0 arg0, ArgT1 arg1) : mArg0(arg0), mArg1(arg1) {}
ArgT0 mArg0;
ArgT1 mArg1;
};
Notice how nice this is: Static function ensures all the hard stuff is done before the object is ever created, lack of default ctor/move means object never exists in an invalid or moved state, private constructor ensures user can't accidentally skip the named ctor.
Unfortunately, because the ctor is private, the std::is_constructable_t<MyType> check fails and therefore the in_place constructor of optional is SFINAE'd out.
This code works if I do one of 2 things, neither of which I want to:
Make the ctor public (But now users of the class can accidentally circumvent the named ctor)
Allow the move operations (But now I have to deal with invalidated objects)
I have also tried this, but it doesn't work because std::optional required a move operator for this to work:
static std::optional<MyType> create() {
// If any of the hard stuff fails, return std::nullopt
return std::optional<MyType>(MyType(5, 'c'));
}
Is there some trick or incantation I may be missing to get this to work, or have I hit the limits of what C++17 will allow?
Thanks!
If you want to make any indirect object construction work (emplace in its various forms, in_place constructors of optional, make_shared, etc) , the constructor in question must be public. You can make a constructor public without allowing all public use by using something called a private key.
Basically, you create a type (call it Key) whose default constructor is private. The class has no members, nor does it do anything. It declares that MyType is a friend of Key; this means that only members of MyType can construct one.
Now, make all of MyType's constructors public, but they all take a Key const& as the first parameter. This means that in theory anyone could call them, but in practice only someone who has a Key instance can actually call them. Members of MyType can create such an instance, and they can pass those instances to optional's in_place constructor or any other indirect mechanism. This effectively gives the indirect construction mechanism private access to the constructor.
This is a standard idiom for dealing with forwarding of private access to a type. Indeed, one could hypothetically write a generic key<T> type like this:
template<typename T>
class key
{
private:
key() = default;
key(int) {} //Not an aggregate
friend T;
};
One small note. Because of an annoyance of C++11 pre-C++20, any type with no members and no constructors other than defaulted/deleted copy/move/default constructors is considered an aggregate. This is true even if you explicitly = default its default constructor. As such, that type can undergo aggregate initialization, which has no public/private distinction. That is, anybody could call your private-key constructors by doing this: MyType({}, <params>);.
To avoid this, you will need to give Key an additional (private) constructor or otherwise prevent it from being an aggregate.
I have recently started using init methods instead of passing parameters to the constructor when designing classes in C++:
Class A {
public:
A();
init(int number);
...
};
Instead of:
Class A {
public:
A(int number);
};
This allows me to use A as a member in other classes like this:
class B {
A m_a;
};
Instead of the way I used to do it:
class B {
A *m_a;
};
(and then allocate m_a in B's constructor.)
The good thing about using init functions is that I don't have to worry about deleting m_a since it will be destroyed when the instance of B is destroyed.
My question is: Is there any downside to using init-methods that I should know about? Will this overflow the stack etc?
Everything is working fine so far, but I thought that I should ask before I write to much code in this way.
It's a horrible pattern.
The object will be in an undefined state between its construction and your calling init. Also you have to think about making init thread safe, along with making init robust if called more than once.
Also note that you can call a constructor from another one from c++11 onwards. So the argument that an init function eliminates duplication of code that could arise from having multiple constructors no longer applies.
You're not obliged to use pointers to have class instances as attributes.
Class B {
public:
explicit B(int i); // notice the explicit, btw
A m_a;
};
B::B(int i)
: m_a(i) { // will call the constructor of "A" with "i" as argument
}
m_a will be destroyed when the instance of B is destroyed too.
By adding an init method, you're defeating the purpose of constructors: you can have an object that's not fully built. Instead of forgetting to delete m_a, you take the risk to forget to init it.
You can store properties by value even if you need non-default constructor to instantiate them. In the constructor of class B you'll need to explicitly instantiate the m_a via intialization list, e.g. B(int number):m_a(number){}. Using initialization functions to overcome this "problem" is really unnecessary here as the language supports this natively.
Observation: The constructor of ClassMain needs to call Init before it can constructor a member variable a. Since the ClassA has no default constructor, the code doesn't compile.
ClassA
{
public:
// This class has no default constructor
ClassA(...){}
};
class ClassMain
{
public:
ClassMain(...) {
Init(...);
a = ClassA(...); // error: ClassA has no default constructor
// a has to been constructed after the Init is called!
}
ClassMain(...) {
Init(...);
call other functions
a = ClassA(...);
}
private:
// initialize environment
void Init(...) {}
private:
ClassA a;
};
Question> The simple solution is to provide a default constructor for ClassA. However, I would like to know whether there is a better solution to address the issue above?
The better solution is not to require an Init function at all. You're trying to reinvent constructors, and breaking their design in the process.
If Init does too much work for a constructor, then do it outside and pass the resulting resources into ClassMain as a constructor argument; notice how you're already doing all the work in the constructor's scope anyway, thereby not gaining anything appreciable over proper initialisation.
Of course, if you must perform a ton of work before initialising a, and you cannot pass in a ClassA& from the outside and initialise from that, then you're simply going to have to have a be an indirect member.
There is one nasty workaround you could use: have Init actually be a base constructor...
The obvious solution is to call Init() from the initializer list of an early member or a base class. Once this subobject is constructed its results can be passed to the constructors of other subobjects. For example, when defining stream classes I typically privately inherit from a virtual base containing the stream buffer:
struct somebuf_base {
somebuf sbuf;
// ...
};
class somestream
: private virtual somebuf_base
, public std::ostream
{
public:
somestream(someargs)
: somebuf_base(someargs)
, std::ostream(&this->sbuf) {
}
// ...
};
Since base classes are constructed in the order they appear but virtual bases before non-virtual bases, the base class containing the sbuf member is constructed first. Its constructor replaces your Init() function.
When using C++ as of the 2011 revision, you might also use forwarding constructors to share logic between multiple constructors.
It's easier to take a pointer to ClassA; So, you can instantiate it whenever you want.(after the init())
If you used a pointer, don't forget to implement the virtual destructor and release the allocated memory for the ClassA *a
If you absolutely must call some function at the start of your constructor, and can't put that setup into some base class or early-constructed member, you could use this ugly trick:
ClassMain::ClassMain(int main_param)
: a( (Init(init_arg), class_a_arg1), class_a_arg2 )
{
}
In this case: No, we cannot avoid that.
The reason is that when calling Init or any other member function you are guaranteed by the language that the object you are in exists. As a is a member of ClassMain it must be constructed before any function in ClassMain can be called.
The only chance that you have here is to refactor the code.
Can one overload a constructor with a private constructor with the same parameters?
Basically if something stores a positive integer, then in the public constructor it would make sure a positive integer was being stored, whereas in a private constructor it doesn't perform the check.
Obviously this example isn't really an appropriate use, but sometimes you want to create an object inside a method and you don't want it to waste time performing full safe initialisation; you may want to just tell it to create something straight away without the special checks (or more prudently heap allocations or something expensive) when you're going to perform them again later or they're just unnecessary, and a method inside the class should be able to use this constructor automatically instead of the other public one with the same parameters.
You cannot overload on acccess like private versus public, but you can overload on the signature: the number of arguments and their types.
Private constructors are quite common.
One usage is for a logically "deleted" constructor (finally directly supported by C++11), and another is for use by a public factory function.
Example:
class A
{
public:
A( int const x)
{
// Whatever, checked construction.
// Perform the check of the x argument.
// Then other things.
// In C++11 it can be done by checking x and forwarding to the
// unchecked constructor in the same class. Not shown here though.
}
private:
enum unchecked_t { unchecked };
A( int const x, unchecked_t )
{
// Unchecked construction.
}
// Methods that possibly use the unchecked constructor.
};
No, you cannot overload a public constructor or another member function with a private one: only the name and the parameter types count for the purpose of overload resolution.
To do what you are looking for, define a private constructor that takes an additional bool parameter that indicates that the parameter checking needs to be performed:
class A {
public:
A(int x) : A(x, true) {}
private:
A(int x, bool check) {
if (check) {
// Perform the check of the x argument
}
}
};
To construct an instance and bypass the check, functions that have access to the private constructor call
A aUnchecked(-123, false);
Checked instances constructed the usual way:
A aChecked(123);
with a private constructor you cant instantiate a class directrly instead you used something called named Constructor Idiom.
other thing you cant inherit the class since the class which wants to inherit will not be able to access the constructor
what you should do is to craete w amethode which is called from the constructor to check