I have a struct A that has several constructors with different data members initialized.
template<typename T>
struct A {
typedef std::vector<T> type1
type1 a;
type1 b;
type1 c;
A(type1 i_a): a(i_a) {
}
A(type1 i_a, type1 i_b): A(i_a), b(i_b) {
}
A(type1 i_a, type1 i_b, type1 i_c): A(i_a, i_b), c(i_c) {
}
};
Error I get is when I instantiate it with say custom_type, the error is
type A<custom_type> is not direct base of A<custom_type> highlighting the constructor I call within another constructor. I am using C++11. What's the problem?
A constructor may initialize its base classes and members, OR delegate to another constructor of the same class, not both.
A(i_a) constructs a complete A object, copying member a and default-constructing b and c. So it doesn't make sense to have A(type1 i_a, type1 i_b): A(i_a), b(i_b) {} - the first initializer has already initialized b. You could instead have
A(type1 i_a, type1 i_b) : A(i_a) { b = std::move(i_b); }
aschepler provides the answer but I wanted to explain what lead to the problem and show 'best practices' for delegating constructors to avoid it.
In your code you have a series of constructors, each more general than constructor they delegate to. That is you're trying to have a constructor delegate to a more specialized constructor that doesn't do everything and then you tack on a bit of work to handle the extra generality. This is backwards from what has turned out to be the most practical way of construction delegation in earlier languages that support it.
What you want instead is to have the most general constructor be the 'root' of the delegation (the 'designated initializer' or 'designated constructor', in other languages). More specialized constructors will do their work using more general constructors, passing them the data for the special case to be handled.
In your case the specialized behavior is to use default values for some members instead of taking initial values from the user. So your more specialized constructors will do their work by passing on the parameter they're given along with default values for the other members.
template<typename T>
struct A
{
typedef std::vector<T> type1;
type1 a;
type1 b;
type1 c;
A(type1 i_a, type1 i_b, type1 i_c): a(i_a), b(i_b), c(i_c) {}
A(type1 i_a, type1 i_b): A(i_a, i_b, {}) {}
A(type1 i_a): A(i_a, {}) {}
};
but you can still call different constructors of the same class from the body of constructor (if for some reason you would want to)
class CComplex{
public:
CComplex(int real1,int image1,char c)
{
cout<<"RealImg";
real=real1;
image=image1;
char* x; char xc=c;x=&xc;
void* v;
f(x);
CComplex ccc(x,v); //this is OK
CComplex cccc(1,2,3); //as this too
}
CComplex():real(0),image(0){cout<<"DEFAULT";}
CComplex(const CComplex &c)
{
real=c.real;
image=c.image;
cout<<"COPY";
}
CComplex& operator=(CComplex const& ref){
cout<<"ASSIGN";
//CComplex* c;
CComplex cobj(43,45,'x');
//c=&cobj;
//CComplex* c=new CComplex(44,45);
return cobj;
}
CComplex(int i1, int i2, int i3){cout<<"\n123!";}
CComplex(const char* y,void* v){cout<<"\nCrefvoid!";}
~CComplex(){cout<<"\n~CComplex(){}";}
public:
void Display(void)
{
cout<<real<<"+"<<image<<"i"<<endl;
}
static bool CComplexComparator(CComplex c1, CComplex c2){return true;}
static void CComplexInit(CComplex& c){
c.real=100;
}
int real,image;
};
Related
I have observed that the following code segfaults at the line ar.p():
#include <iostream>
class A
{
public:
virtual void p() { std::cout<<"A!\n"; }
};
class B : public A
{
public:
void p() { std::cout<<"B!\n"; }
};
struct Param
{
enum {AA, BB} tag;
union {
A a;
B b;
};
Param(const A &p)
: tag(AA) {a = p;}
A &get() {
switch(tag) {
case AA: return a;
case BB: return b;
}
}
};
int main() {
A a;
a.p();
Param u(a);
A &ar = u.get();
ar.p();
}
However, when I change the Param constructor to:
Param(const A &p)
: tag(AA), a(p) {}
it does not segfault anymore.
I think it has something to do with the way the vtable ptr for union member a is initialized, but I'd like to understand this bug better.
On coliru: http://coliru.stacked-crooked.com/a/85182239c9f033c1
The union doesn't have an implicit constructor, you have to add your own constructor to the union which initializes one of the members of the union. I think this is because the compiler can't know whether you want to initialize a or b. You may also need an assignment operator and destructor. See also this question: Why does union has deleted default constructor if one of its member doesn't have one whatsoever?
The constructor should use placement new or it can use a member initializer to construct one of the union members, as you do in your alternative constructor.
If you want to assign something to b afterwards, you have to destruct a using a.~A(), and then initialize b with placement new.
If you have members in the union with a non-trivial destructor then the union must have a destructor which calls the destructor on the member which is used at that point.
In your original code the assignment operator and the p() method are called without running a constructor first, leading to the crash.
I wonder why people say:
"Inheriting class doesn't inherit the constructor".
If you could CAN use the parent class' constructor, and the parameterless constructor are called automatically no matter what.
Example:
#include <iostream>
using namespace std;
class A {
private :
int x;
public :
A () {
cout << "I anyway use parameter-less constructors, they are called always" << endl;
}
A (const int& x) {
this->x = x;
cout << "I can use the parent constructor" << endl;
}
};
class B : public A {
private :
int y;
public :
B() {
}
B (const int& x, const int& y) : A (x) {
this->y = y;
}
};
int main() {
B* b = new B(1,2);
B* b1 = new B();
return 0;
}
http://ideone.com/e.js/6jzkiP
So is it correct to 'say', constructors are inherited in c++ ? What is exact definition of "inherit" in programming languages ?
Thanks in advance.
I wonder why people say: "Inheriting class doesn't inherit the constructor".
Perhaps it is best to illustrate this with an example:
struct Foo
{
Foo(int, int) {}
};
struct Bar : Foo
{
};
What it means is that there is no Bar::Bar(int, int) constructor that you can call, despite the existence of a constructor with the same parameter list in the base class. So you cannot do this:
Bar b(42, 42);
In C++11, you can actually inherit constructors, but you must be explicit about it:
struct Bar : Foo
{
using Foo::Foo;
};
Now, you can say Bar b(42, 42);
What they mean is that constructor signatures are not inherited.
In your example, B does not have a constructor taking a single const int& even though its base class does. In this sense it has not "inherited" the constructor (but can still make use of it).
I think what they mean is:
struct A {
A(int, int) { }
};
struct B : public A {
};
int main()
{
A a(1, 2); // ok
B b(1, 2); // error
}
To compare with “non-special” member functions:
struct A {
void f() { }
};
struct B : public A {
};
int main()
{
A a;
B b;
a.f(); // ok
b.f(); // ok too
}
But of course, from within B you can call accessible A constructors (as automatically generated ones do). Ditto for the destructor.
Note that in C++11 you can use the “inheriting constructors” feature:
struct A {
A(int, int) { }
};
struct B : public A {
using A::A;
};
int main()
{
A a(1, 2); // ok
B b(1, 2); // ok now
}
A derived class can/must see base class constructors in order to invoke them, for consistency. However, their signature is not exposed in the derived class, hence, one cannot construct the class without an explicitly defined constructor, which forwards the required arguments to the base class constructor.
In C++11, one can inherit constructors: What is constructor inheritance?
Another approach to circumvent 'proxy constructors' in C++ < 11: How to define different types for the same class in C++
In your example, the default ("parameterless" as you say) constructor of B does invoke the default constructor of A, but this does not mean that B "inherited" that constructor, only that it "has access to" it. That is, A's default constructor is accessible from within B, yet it is not accessible from outside (no one can use A's default constructor from outside to construct an instance of B).
Another way to look at it is to ask, what is something frustrating about constructors and inheritance in C++? A common answer from some people (including myself) would be that there is no automatic facility which allows "pass-through" construction of base classes taking arguments from derived class constructors without explicitly declaring and defining the latter.
Background:
What I would like to do is something similar to the following (the code does not work):
class A {
public:
A(TypeX a)
{
/* initialize using TypeX */
}
A(TypeY a)
{
/* initialize using TypeY */
}
};
class B {
private:
A a;
static const TypeX x;
static const TypeY y;
public:
B(bool useTypeX)
: a(useTypeX ? x : y)
{}
};
TypeX B::x;
TypeY B::y;
This would be my desired code (if the language supported it), but the ternary operator in the initializer-list construction of B::a does not perform the overload resolution for the two disparate types at compile-time (see: https://stackoverflow.com/a/8535301/1689844).
Please note, I only have control over the design of the B class. Class A, TypeX and TypeY are disparate types and out of my control (also, TypeX and TypeY do not share a common base class nor is TypeX able to be converted into TypeY or vice-versa). Also, class A is expensive to initialize (so copy constructors are not feasible).
Question:
I would like to know if anyone knows of a more elegant solution to achieve my desired behavior than the following implementation of class B. Answers that utilize C++11 features are welcome, but I am confined to using C++03 and therefore I will only accept an answer that utilizes C++03 features:
class B {
private:
SomeSmartPointer<A> a;
static const TypeX x;
static const TypeY y;
public:
B(bool useTypeX)
{
// SomeSmartPointer is a smart pointer
// which uses reference-counting to
// delete allocated memory when the
// reference count is 0 and it is
// copy-constructable
if (useTypeX)
{
SomeSmartPointer<A> tmp(x);
a = tmp;
}
else
{
SomeSmartPointer<A> tmp(y);
a = tmp;
}
}
};
TypeX B::x;
TypeY B::y;
If A is copy constructable (or move constructable, but that's not relevant since you're not using C++11), then you can do
class B {
private:
A a;
static const TypeX x;
static const TypeY y;
static A initA(bool useTypeX)
{
if (useTypeX)
return A(x);
else
return A(y);
}
public:
B(bool useTypeX)
: a(initA(useTypeX))
{}
};
Edit: Of course, thinking about it, this is just as legal, eliminating the need for an extra function. The key is that you're explicitly creating them. See https://ideone.com/yUIF0Z
B(bool useTypeX) : a( useTypeX ? A(x) : A(y) ) {}
How to use PIMPL design for parameterized constructor?
/* ProcessImpl.h */
class ProcessImpl {
public :ProcessImpl();
ProcessImpl(ProcessID thirdParty_pid);
~ProcessImpl();
}
/* Process.h */
class Process {
public:virtual ~Process () {};
Process();
Process(ProcessID thirdParty_pid);
protected:
void createImpl();
private:
ProcessImpl * _impl;
}
/* Process.cpp */
Process::Process():_impl(NULL) {
}
Process::Process(ProcessID thirdParty_pid) {
createImpl();
_impl->ProcessImpl(ldframework::ProcessID thirdParty_pid);
}
void Process::createImpl(){
if(this->_impl == NULL) {
this->_impl = new ProcessImpl();
}
}
When I compile this I am getting error:
Process.cpp: error: invalid use of class ProcessImpl
This is the line throwing error _impl->ProcessImpl(ldframework::ProcessID thirdParty_pid)
Please help
Since your code is not valid C++ I won't jump into conclusions about your actual implementation, so I will start from the beginning:
If a class has a parametrized constructor, the parameters are needed to directly or indirectly initialize class members and base classes. Since a pimpl'd class has no data members of its own (except the pimpl), constructor parameters are needed only for the initialization of the implementation class.
There are two extremes of the pimpl idiom implementation:
All the logic goes into the implementation class, and the outer class is only a dumb fassade, forwarding any calls to the pimpl.
The logic remains in the outer class, the pimpl is only a dumb bundle of data.
Of course, in practice, anything in between is possible.
In case 1, the outer class' constructor signatures should be the same as the signature of the implementation class' constructors and just pass any arguments to the pimpl constructors:
Foo.h
class Foo {
struct FooImpl;
std::unique_ptr<FooImpl> pImpl;
public:
~Foo();
Foo(A const& a);
Foo(B b, C* c, D& d);
};
Foo.cpp
struct Foo::FooImpl {
FooImpl(A const& a);
FooImpl(B b, C* c, D& d);
/* Logic goes here */
};
Foo::~Foo() {} //defined here for correct deletion of the unique_ptr
Foo::Foo(A const& a)
: pImpl(std::make_unique<FooImpl>(a))
{}
Foo::Foo(B b, C* c, D& d)
: pImpl(std::make_unique<FooImpl>(std::move(b), c, d))
{}
Together:
Use the same constructor signatures for the class and the pimpl-class, each class constructor just calls the corresponding pimpl-constructor
Parameters taken by reference or pointer are passed as-is to the pimpl constructor
Parameters taken by value are moved to the pimpl constructor (forwarding)
That is the simplest possible solutution where the constuctor logic is entirely implemented inside the implementation class.
In the other case, where the pimpl class is only a bundle of data, you will have the logic inside the outer class` constructor, like this:
struct Foo::FooImpl {
FooImpl(A const& a, B b, E e, F f);
A a;
};
Foo::Foo(B b, C* c, D& d)
: pImpl(std::make_unique<FooImpl>(A(), std::move(b), calcE(c,d), getSomeF())
{
pImpl->a = someValueForA();
}
You see, the strategy to implement the constructors depends on your strategy to implement the pimpl idiom alltogether. Just make sure you are somewhat consistent in either delegating the logic to the pimpl class or leaving it in the main class.
Just construct the pimpl in the constructor.
Note that you should also implement a copy constructor and assignment operator as copying the object will result in undefined behaviour when both copies are destructed.
Ideally the pimpl should always be valid to avoid checking if it is valid all the time, but going by your code, you could perhaps have the following:
class Process {
public:
virtual ~Process () {
};
Process() {
// Ideally the impl_ pointer should be intialized to avoid
// having to check it in every function that uses it..
}
Process(ProcessID pid) {
impl_.reset(new ProcessImpl(pid));
}
Process(Process const& rhs) {
if (rhs.impl_.get()) {
impl_.reset(new ProcessImpl(*rhs.impl_));
}
}
Process& operator=(Process const& rhs) {
if (this != &rhs) {
if (rhs.impl_.get()) {
impl_.reset(new ProcessImpl(*rhs.impl_));
}
else {
impl_.reset();
}
}
return *this;
}
private:
std::unique_ptr<ProcessImpl> impl_;
};
Say I have a class with some const reference member variable and I would like to forbid a certain type of construction. So I would declare the according constructor private. Of course, a constructor must initialise all const reference member variables of the class. Doing so, however, results in odd looking code:
class A {
};
class B {
B(const A& a): host(a) {}
private:
B():host(A()) {} // This is ugly and not needed !!
const A& host;
};
Is there another way to prohibit a certain construction type except than declaring the constructor private? I do not want to let the compiler write a constructor for me.
Simply don't define this:
B():host(A()) {} // This is ugly and not needed !!
That is, the following should do what you want to do:
class B {
B(const A& a): host(a) {}
private:
//B():host(A()) {} // This is ugly and not needed !!
const A& host;
};
The idea is if you've defined a constructor that takes parameter(s), then the default constructor is not generated by the compiler. That means, instances of the above class cannot be default created!
B b1; //error - needs default constructor which doesn't exist!
B b2(a); //ok - only way to create an instance!
C++11 solution
In C++11, you can explicity tell the compiler not to generate a particular constructor as:
struct B
{
B(const A &a) {}
B() = delete; //disable
};
Not only that. There is more to it, as explained below:
Now the interesting part
You can also selectively disable constructor(s) for selected types which makes delete more interesting. Consider this,
struct A
{
A (int) {}
};
Object of this class can be created not only with int argument, but any type which implicitly converts to int. For example,
A a1(10); //ok
A a2('x'); //ok - char can convert to int implicitly
B b;
A a3(b); //ok - assume b provides user-defined conversion to int
Now suppose, for whatever reason, I don't want the users of class A to create objects with char or class B , which fortunately or unfortunately can implicitly convert to int, then you can disable them as:
struct A
{
A(int) {}
A(char) = delete; //disable
A(const B&) = delete; //disable
};
Now here you go:
A a1(10); //ok
A a2('x'); //error
B b;
A a3(b); //error - assume (even if) b provides user-defined conversion to int
Online Demo : http://ideone.com/EQl5R
The error messages are very clear:
prog.cpp:9:5: error: deleted function 'A::A(char)'
prog.cpp:10:5: error: deleted function 'A::A(const B&)'
Just leave it out. As soon as you provide a custom constructor, no other constructor is auto-generated (except for a copy constructor).
If you want to forbid any construction – ending up with a class that has only static members – you can simply declare the constructor as private, and not define it. Such a class is very rarely useful in C++ (since you cannot create instances of it); the only purpose that I can think of is to implement trait classes:
template <typename T>
struct type_to_color {
static char const* value() { return "blue"; }
private:
type_to_color();
};
template <>
struct type_to_color<int> {
// Integers are red!
static char const* value() { return "red"; }
private:
type_to_color();
}
char const* char_color = type_to_color<char>::value();
char const* int_color = type_to_color<int>::value();
However, this is extremely uncommon: trait classes are abundant in C++ but they never declare their constructors as private, it’s just assumed that everybody knows not to instantiate them.
I'll post the C++11 solution: delete the constructor.
class B {
B() = delete;
B(const A& a): host(a) {}
private:
const A& host;
};
As Konrad Rudolph sayd: as soon you provide a custom constructor, no other constructor is auto-generated (except for a copy constructor).
Therefore, other options are:
Declare the constructor private (so that you can't inherit from your class), but do not provide a definition:
class B {
public:
B(const A& a): host(a) {}
private:
B(); // not implemented!
const A& host;
};
Or in C++11, as R. Martinho Fernandes says:
class B {
public:
B() = delete;
B(const A& a): host(a) {}
private:
const A& host;
};