Is it possible to "add" to the default copy constructor?
Eg. For this class:
class A
{
public:
int a;
int* b;
};
I want to just write
A::A(const A& rvalue):
a(rvalue.a),
b(new int(*(rvalue.b)))
{}
without the a(rvalue.a) part.
(Ignore the bad/ugly code and possible memory leaks)
What you ask for is impossible. Once you declare your own copy constructor the compiler will not generate a copy constructor for you. That means you won't be able to simply add or augment the default copy constructor because it won't exist. It's all or nothing, so to speak.
it is impossible. However, if you want to reduce redundant code for a large number of "default copied" fields, it may be achieved with intermdiate inheritance:
struct A1 {
int a1;
int a2;
// ....
int aN;
};
struct A:public A1
{
int* b;
A(const A& rhs): A1(rhs), b(new int(*(rhs.b))) {}
};
What you want to do is not nartually supported by C++ : you cannot have half default constructor.
But what you want to achieve can be done by the little trick below:
please note this small demo below have a lot defects(memory leak etc), so it's ONLY for demostration the tentative solution only:
//class A hasa large number date members(but all can take advantage of default
//copy constructor
struct A{
A(int i):a(i){}
int a;
//much more data memberS can use default copy constructor all in class A
};
//class B is simply wrapper for class A
//so class B can use the default constructor of A
//while just write copy constructor for a raw pointer in it's copy constructor
//I think this is what OP want ?
struct B
{
B(int i,int j):m_a(i),m_b(new int(j)){}
B(const B & rval):
m_a(rval.m_a),
m_b(new int(*rval.m_b))
{
}
A m_a;
int * m_b;
};
int main()
{
B c(2,3); // a=2, *m_b=3
B d(c); //after copy constructor, a=2, *m_b=3
}
Related
In my code, I used inner-class as an iterator for another class.
To simplify the situation, the code can be shown as follows:
class A {
public:
class B {
public:
explicit B(void):idx(3){}
B(const B&b) {
idx = 4; // never be called
}
private:
int idx=0;
};
B getB()
{ return A::B(); }
};
void test2(){
A a;
A::B b = a.getB(); // b.idx ends with value of 3
}
The problem is that, in test2() , while running A::B b = a.getB();, the copy-constructor method wasn't called. And the b ends with value 3.
Why is this?
For another problem confused me
class A {
public:
class B {
public:
explicit B(void):idx(3){}
explicit B(const B&b) {} // C2440, cannot convert from "A::B" to "A::B"
private:
int idx=0;
};
B getB()
{ return A::B(); }
};
Why will C2440 ocurrs with two types exactly the same?
What you are seeing is copy elision. In order to make it easier for optimizers to speed up the generated code, the C++ standard allows copy constructors to be skipped in certain situations.
C++ language does not guarantee the side effects of copy (nor of move) constructors to be observable in the abstract machine. This non-guarantee lets the compiler avoid temporary objects when they are not necessary, thereby avoiding copying of those objects in the concrete machine.
Your program relies on the side effects of a copy constructor. This is bad; Don't do it.
I have these structs.
struct V
{
int data[2];
V(int a,int b)
{
data[0] = a;
data[1] = b;
}
}
typedef std::vector<int> X;
struct A
{
B<V> member1;
B<X> member2;
A(V member1_, X member2_) : member1(member1_),member2(member2_){}
}
template<typename T>
struct B
{
T data;
B(T data_){data = data_;}
}
How do I create an object of struct A? I wish to declare an object A like so
A a;
and then use it later to assign member1 to it. This is because I would not know B's data until later in the program run. But the compiler would not let me and complains about default constructor in B, saying I don't have one. How do I write default constructors for B and A then while B is a template? Is there a better way to achieve this?
Thanks for your help.
Give struct B an empty default constructor. It will run the default constructor of data, too. You just need to make sure that T has a default constructor, too (actually, the current code of yours requires that, too - members are constructed before opening brace of constructor).
How can I achieve this behavior?
class A
{
int x;
public:
A(int x) : x(x) {}
};
class B
{
A a; // here is the problem
public:
B() : a(1) {} // solution i found
};
int main(void)
{
B b;
return 0;
}
I'm wondering if there is another way of making this work except the answer I found.
No. That's the proper solution. You explicitly state you don't want it to be possible to initialize A with no parameters, so this outcome shouldn't surprise you.
Or provide a default for x:
class A
{
int x;
public:
A(int x = 1) : x(x) {}
};
making it a default constructor.
Add a second, default constructor to A:
class A
{
int x;
public:
A(int x) : x(x) {}
A() : x(1) {}
};
Yes, in C++11, you could just write this:
class B
{
A a(1); //C++11 support this! (though the compilers may not, now)
public:
B() {} //nothing here!
};
Or this,
A a{1}; //using uniform initialization
You should remember that when you add one constructor explicitly then default constructor will be not created automaticly. It is a only a default constructor. Copy constructor will be created.
Also remember of rule of three:
The rule of three (also known as the Law of The Big Three or The Big Three) is a rule of thumb in C++ that claims that if a class defines one of the following it should probably explicitly define all three[1]:
destructor
copy constructor
copy assignment operator
>
I'm sure you already know this but you can make "a" a pointer to an object of type A: that will allow you to control when the object is instantiated, and thus what value can be passed into the A constructor at run time (will require deletion obviously)
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;
};
I'm not used to c++ and I'm having a problem writing a constructor.
See this example, is a short version of the code I'm working on:
class B {
public:
B(int x);
}
class A {
public:
B b;
A(){
// here I have to initialize b
}
}
That throws a compiler error since I need to initialize b in A's constructor because B does not have a default constructor.
I think I have do it in the initialization list, but the B(int x) argument is a value I have to calculate with some algorithm, so I don't know how this should be properly done, or if I'm missing something or doing it wrong.
In other language like java I would have a reference to B and initialize it inside the A's constructor after the other code I need to get the value for the initialization.
What would be the right way to initialize b in this case?
Thanks!
You can invoke functions in your constructor initializer list
class B {
public:
B(int x);
}; // note semicolon
class A {
public:
B b;
A()
:b(calculateValue()) {
// here I have to initialize b
}
static int calculateValue() {
/* ... */
}
}; // note semicolon
Note that in the initializer list, the class is considered completely defined, so you can see members declared later on too. Also better not use non-static functions in the constructor initializer list, since not all members have yet been initialized at that point. A static member function call is fine.
You use an initializer list, something like this:
A() : b(f(x)) {}
#include<iostream>
class B {
public:
B(){} // A default constructor is a must, if you have other variations of constructor
B(int x){}
}; // class body ends with a semicolon
class A {
private:
B b;
public:
A(){
// here I have to initialize b
}
void write(){
std::cout<<"Awesome";
}
};
int main(){
A a;
a.write();
}
In C++, if you have a constructor that takes an argument, a default constructor is a must, unlike other languages as Java. That's all you need to change. Thanks.