Im receiving error C2082: redefinition of formal parameter 'rval' in this code while trying to call base copy ctor explicitly:
#include <iostream>
using namespace std;
class Base
{
public:
Base(const Base& rhs){ cout << "base copy ctor" << endl; }
};
class Derived : public Base
{
public:
Derived(const Derived& rval) { Base(rval) ; cout << "derived copy ctor" << endl; }
// error C2082: redefinition of formal parameter 'rval'
};
int main()
{
Derived a;
Derived y = a; // invoke copy ctor
cin.ignore();
return 0;
}
However if do it like this:
Derived(const Derived& rval) { Base::Base(rval) ; cout << "derived copy ctor" << endl; }
then is OK.
Why am I asking this?
according to the answers on StackOwerflow
I do not have to use operator :: to access base copy ctor,
so why do I receive this error?
btw: I'm using visual studio 2010.
I'm having one more question:
Do I have to call base's move constructor in user defined move constructor of derived class?
To call the base constructor you need to put the call in the member initalization list
class Derived : public Base
{
public:
Derived(const Derived& rval) : Base(rval)
{
cout << "derived copy ctor" << endl;
}
};
Assuming that you mean 'move' constructor is the copy constructor - Yes. You will have to call the Base's constructor. Otherwise the definition if the base object within the derived object will not be complete. You can either call a copy constructor or a normal constructor of the base class.
Related
Why aren't copy constructors chained (like default ctors or dtors) so that before the derived class's copy constructor is called, the base class's copy constructor is called? With default constructors and destructors, they are called in a chain from base-to-derived and derived-to-base, respectively. Why isn't this the case for copy constructors? For example, this code:
class Base {
public:
Base() : basedata(rand()) { }
Base(const Base& src) : basedata(src.basedata) {
cout << "Base::Base(const Base&)" << endl;
}
void printdata() {
cout << basedata << endl;
}
private:
int basedata;
};
class Derived : public Base {
public:
Derived() { }
Derived(const Derived& d) {
cout << "Derived::Derived(const Derived&)" << endl;
}
};
srand(time(0));
Derived d1; // basedata is initialised to rand() thanks to Base::Base()
d1.printdata(); // prints the random number
Derived d2 = d1; // basedata is initialised to rand() again from Base::Base()
// Derived::Derived(const Derived&) is called but not
// Base::Base(const Base&)
d2.printdata(); // prints a different random number
The copy constructor doesn't (can't) really make a copy of the object because Derived::Derived(const Derived&) can't access basedata to change it.
Is there something fundamental I'm missing about copy constructors so that my mental model is incorrect, or is there some arcane (or not arcane) reason for this design?
The copy constructor doesn't (can't) really make a copy of the object because Derived::Derived(const Derived&) can't access pdata to change it.
Sure it can:
Derived(const Derived& d)
: Base(d)
{
cout << "Derived::Derived(const B&)" << endl;
}
If you don't specify a base class constructor in the initializer list, its default constructor is called. If you want a constructor other than the default constructor to be called, you must specify which constructor (and with which arguments) you want to call.
As for why this is the case: why should a copy constructor be any different from any other constructor? As an example of a practical problem:
struct Base
{
Base() { }
Base(Base volatile&) { } // (1)
Base(Base const&) { } // (2)
};
struct Derived : Base
{
Derived(Derived&) { }
};
Which of the Base copy constructors would you expect the Derived copy constructor to call?
You can:
Derived(const Derived& d) : Base(d) {
cout << "Derived::Derived(const B&)" << endl;
}
This calls the Base copy constructor on the Base sub-object of d.
The answer for 'why' I don't know. But usually there's no answer. The committee just had to choose one option or the other. This seems more consistent with the rest of the language, where e.g. Derived(int x) won't automatically call Base(x).
That's because every constructor calls by default the default base constructor:
Derived(const Derived& d) {
cout << "Derived::Derived(const B&)" << endl;
}
will call Base().
This is defined by the standard. I for one prefer it like this rather than calling the copy constructor on the class. You can of course call it explicitly.
This is my class hierarchy.
#include<iostream>
using namespace std;
class baseClass
{
public:
int var;
int* varPtr;
baseClass(int value) : var(value), varPtr(&var)
{
cout << "baseClass constructor" << endl;
}
};
class derivedClass : public baseClass
{
public:
derivedClass(int value) : baseClass(value)
{
cout << "derivedClass constructor" << endl;
}
derivedClass(const derivedClass& objToCopy)
{
cout << "derivedClass copy constructor" << endl;
}
};
int main(int argc, char** argv)
{
derivedClass derivedObj1(5);
derivedClass derivedObj2(derivedObj1);
return 0;
}
This code gives me a no default constructor error. Which is correct as I don't have a default constructor defined. Now my question is when I call the copy constructor of baseClass from derivedClass.
#include<iostream>
using namespace std;
class baseClass
{
public:
int var;
int* varPtr;
baseClass(int value) : var(value), varPtr(&var)
{
cout << "baseClass constructor" << endl;
}
};
class derivedClass : public baseClass
{
public:
derivedClass(int value) : baseClass(value)
{
cout << "derivedClass constructor" << endl;
}
derivedClass(const derivedClass& objToCopy) : baseClass(objToCopy) // <- ADDED
{
cout << "derivedClass copy constructor" << endl;
}
};
int main(int argc, char** argv)
{
derivedClass derivedObj1(5);
derivedClass derivedObj2(derivedObj1);
return 0;
}
Now I get no error although I have not defined a copy constructor. There is no constructor that takes a reference of baseClass. Why isn't the compiler not complaining? Why is it happy to just do bitwise copy when I'm explicitly calling for the copy constructor? Why there is no error saying that baseClass(const baseClass&) undefined?
Thank you.
Copy-constructors are implicitly added to the class if you do not provide one. In order to prevent copying of your class, you can delete the compiler-generated one, like so:
baseClass(const baseClass& objToCopy) =delete;
The compiler errors in the first program because it attempts to call a no-argument constructor instead of a copy constructor to construct the base-class part of the object. Since you have already defined a custom constructor for the class, the default no-argument version is not implicitly generated.
In derived class the copy constructor is defined that way :
derivedClass(const derivedClass& objToCopy)
{
cout << "derivedClass copy constructor" << endl;
}
By default, the copy constructor of a derived class uses the copy constructor of base class but you were explicitely declaring a copy constructor without specifying how you wanted to construct the base class object, so the compiler tried to use the default constructor.
You should write :
derivedClass(const derivedClass& objToCopy): baseClass(objToCopy.value)
{
cout << "derivedClass copy constructor" << endl;
}
to correctly use the explicit base constructor.
I believe, the reason for this behavior has to do with constructor delegation since C++11.
Why aren't copy constructors chained (like default ctors or dtors) so that before the derived class's copy constructor is called, the base class's copy constructor is called? With default constructors and destructors, they are called in a chain from base-to-derived and derived-to-base, respectively. Why isn't this the case for copy constructors? For example, this code:
class Base {
public:
Base() : basedata(rand()) { }
Base(const Base& src) : basedata(src.basedata) {
cout << "Base::Base(const Base&)" << endl;
}
void printdata() {
cout << basedata << endl;
}
private:
int basedata;
};
class Derived : public Base {
public:
Derived() { }
Derived(const Derived& d) {
cout << "Derived::Derived(const Derived&)" << endl;
}
};
srand(time(0));
Derived d1; // basedata is initialised to rand() thanks to Base::Base()
d1.printdata(); // prints the random number
Derived d2 = d1; // basedata is initialised to rand() again from Base::Base()
// Derived::Derived(const Derived&) is called but not
// Base::Base(const Base&)
d2.printdata(); // prints a different random number
The copy constructor doesn't (can't) really make a copy of the object because Derived::Derived(const Derived&) can't access basedata to change it.
Is there something fundamental I'm missing about copy constructors so that my mental model is incorrect, or is there some arcane (or not arcane) reason for this design?
The copy constructor doesn't (can't) really make a copy of the object because Derived::Derived(const Derived&) can't access pdata to change it.
Sure it can:
Derived(const Derived& d)
: Base(d)
{
cout << "Derived::Derived(const B&)" << endl;
}
If you don't specify a base class constructor in the initializer list, its default constructor is called. If you want a constructor other than the default constructor to be called, you must specify which constructor (and with which arguments) you want to call.
As for why this is the case: why should a copy constructor be any different from any other constructor? As an example of a practical problem:
struct Base
{
Base() { }
Base(Base volatile&) { } // (1)
Base(Base const&) { } // (2)
};
struct Derived : Base
{
Derived(Derived&) { }
};
Which of the Base copy constructors would you expect the Derived copy constructor to call?
You can:
Derived(const Derived& d) : Base(d) {
cout << "Derived::Derived(const B&)" << endl;
}
This calls the Base copy constructor on the Base sub-object of d.
The answer for 'why' I don't know. But usually there's no answer. The committee just had to choose one option or the other. This seems more consistent with the rest of the language, where e.g. Derived(int x) won't automatically call Base(x).
That's because every constructor calls by default the default base constructor:
Derived(const Derived& d) {
cout << "Derived::Derived(const B&)" << endl;
}
will call Base().
This is defined by the standard. I for one prefer it like this rather than calling the copy constructor on the class. You can of course call it explicitly.
If I make a size 2 std::vector of a derived class, the constructor is called only once. If I make a size 2 vector of a base class, the constructor is called twice.
I usually wouldn't post the complete code that duplicates an issue, but in this case it can be made quite short:
#include <iostream>
#include <vector>
class Base {
public:
Base() { std::cout << "base constructor" << std::endl; }
virtual ~Base() {}
};
class Derived : public Base {
public:
Derived() { std::cout << "derived constructor" << std::endl; }
};
int main() {
std::vector<Base> base(2);
std::cout << "----------------" << std::endl;
std::vector<Derived> derived(2);
return 0;
}
The output of the above for me is:
base constructor
----------------
base constructor
derived constructor
Why is the output not the following:
base constructor
base constructor
----------------
derived constructor
derived constructor
I'm using gcc 4.5.2 on Linux.
You're deceiving yourself: A single default construction of the derived object calls both constructors.
Now, what you are not seeing is the copy constructor, which does in fact get called twice in both cases.
The constructor of vector that you're calling makes one default construction of its value type, and then copies that into each element:
//std::vector<Derived> v(2);
std::vector<Derived> v(2, Derived()); // same thing!
This is a bit of an extension on what Kerrek wrote:
#include <iostream>
#include <vector>
class Base {
public:
Base() { std::cout << "base constructor" << std::endl; }
virtual ~Base() {
}
Base(const Base&){
std::cout << "copy base constructor" << std::endl;
}
};
class Derived : public Base {
public:
Derived() { std::cout << "derived constructor" << std::endl; }
Derived(const Derived& d):Base((const Base) d){
std::cout << "copy derived constructor" << std::endl;
}
};
int main() {
std::vector<Base> base(2);
std::cout << std::endl;
std::vector<Derived> derived(2);
return 0;
}
The output from this is:
base constructor
copy base constructor
copy base constructor
base constructor
derived constructor
copy base constructor
copy derived constructor
copy base constructor
copy derived constructor
This is the output I get from VC++ 2010:
base constructor
base constructor
base constructor
derived constructor
base constructor
derived constructor
Press any key to continue . . .
Whereas with (GCC) 4.6.1
g++ -o test test.cpp
sashan#cyclops cpp $ ./test
base constructor
base constructor
derived constructor
So it looks like it's an implementation difference....which is kinda puzzling.
Update
Compiling with c++0x gives:
sashan#cyclops cpp 1 $ g++ -std=c++0x -o test test.cpp
sashan#cyclops cpp $ ./test
base constructor
base constructor
base constructor
derived constructor
base constructor
derived constructor
Which supports Kerrek SB's comments and answer.
class base {
public:
base(){
cout << "base constructor" << endl;
}
base(const base& rh) {
cout << "base copy constructor" << endl;
}
};
//case 1:
class der : public base {
};
//case 2:
class der : public base {
public:
der(){
cout << "der constructor" << endl;
}
der(const der& rh) {
cout << "der copy constructor" << endl;
}
};
int main() {
der d;
der d1(d);
}
case 1: der d1(d); invokes base class copy constructor whereas in
case-2, base class default constructor and der class copy constructor
is invoked.
Can anyone explain the logic?
In case 1, you get the default copy constructor synthesized by the compiler. This is defined to copy bases and members.
In case 2, you defined your own copy constructor, which does what you tell it to do. You didn't put anything in the initializer list for the base class, so the base is default-constructed[*], same as any other constructor that doesn't explicitly initialize the base. If der had any data members, those would not be copied either.
[*] or one of the other kinds of initialization that amounts to the same thing for non-POD classes. I can never remember those details.
Derived copy constructor will not call base class copy constructor itself by default. When you don't tell the derived class copy constructor to call the base class copy constructor , it will still need to construct the base sub-object, so it will have to call the base default constructor.
But in the example below you , you will see you can add calling to base copy constructor in the member initilize list explicitly of derived class:
class base {
public:
base(int i):m_i(i){
cout << "base constructor" << endl;
}
base(const base& rh) {
m_i = rh.m_i;
cout << "base copy constructor" << endl;
}
private:
int m_i;
};
//case 2:
class der : public base {
public:
der(int i,int j):base(i),m_j(j){
cout << "der constructor" << endl;
}
der(const der& rh):base(rh) {
m_j = rh.m_j;
cout << "der copy constructor" << endl;
}
private:
int m_j;
};
int main() {
der d(1,2);
der d1(d); //d1.m_i = 1, d1.m_j = 2
}
//result
//base copy constructor
//der copy constructor
In the first case, you are not specifying constructors for der, therefore the compiler decides for you, that is copy the data of d to d1 individually, invoking copy constructor of base in the process.
In the second case, you have specified the copy constructor, in which you do not invoke the copy constructor of base yourself. Since you have overridden the copy constructor of der (which tells the compiler to do what you say, not what it wants), the compiler cannot assume you intended to invoke the copy constructor of base too.
Basically there is a call to one copy-con. So in case-2 the copy-con of der is called, and if you like you can use the copy-con of the base in the code. In case one, since you didn't implemented the copy-con in der it calls the function from his base, like it would do with any function that is only implemented in a base class.