While creating object we can have implicit or explicit call to constructor
Base obj;
Base obj = Base(1,2);
Both these object creation methods are working fine, until I include copy constructor in code.
Here is the code snippet.
#include<iostream>
using namespace std;
class Base {
public:
Base(int x, int y) {}
Base() {}
Base(Base& o){}
private:
int a;
int b;
};
int main() {
Base obj = Base(10,20); /*This line throws error after including copy Ctor*/
Base obj2 = obj;
}
I am using Linux g++ compiler.
Error : no matching function for call to ‘Base::Base(Base)’
Am I missing something.
Copy Constructor should be of following form, to enable the temporary object creation with Base(10,20)
Base(const Base& o){}
// ~~~~ notice `const`
Alternatively, you can use move constructor with C++11, to allow temporary objects
Base(Base &&o){}
You have two possibilities. Either change the declaration of the copy constructor like
Base( const Base &o){}
Or add a move constructor
Base(Base &&o){}
For example
#include<iostream>
using namespace std;
class Base {
public:
Base(int x, int y) {}
Base() {}
Base(Base& o){}
Base( Base && ){}
private:
int a;
int b;
};
int main() {
Base obj = Base(10,20); /*This line throws error after including copy Ctor*/
Base obj2 = obj;
}
The problem with your code is that expression Base(10,20) creates a temporary object that can be binded only with a constant reference.
in fact you need not to define the copy constructor explicitly for this simple class.
Related
I have a problem with instantiating a class as a member of another class.
Here is my code:
class myClassA{
public:
myClassA(){
printf("myClassTwo ctor");
}
void doSomething(){ printf("myClassA did something\r\n");}
};
class myClassB{
public:
myClassB(int i){
printf("myClassA ctor got %d\r\n",i);
threeMyI = i;
}
private:
int threeMyI;
};
class myClassC{
public:
myClassC(){
printf("C ctor without params\r\n");
}
myClassA instanceA;
myClassB instanceB(29); //<== Not working why??
};
I have a class myClassC which I want to have two members, one of type myClassA and one myClassB. This works well for myClassA. But as soon as I try to create an instance of myClassB, which has an ctor parameter, it fails with the following compiler error:
..\src\main.cpp:34:21: error: expected identifier before numeric constant
myClassB instanceB(29); //<== Not working why??
..\src\main.cpp:34:21: error: expected ',' or '...' before numeric constant
In my main function this type of declaration works well:
int main(void){
printf("class test\r\n");
myClassC instanceC1;
myClassA instanceA1;
myClassB instanceB1(25);
return 0;
}
But I have no idea what makes the big difference when instantiating a class with ctor parameters. Hope somebody can give me an hint what I'm doing wrong.
You can only declare member variables, you cannot instantiate them.
To invoke the constructor of a member-variable you can use the memberwise initialization paradigm in your own constructors:
struct A { // same as class A but public by default
int m_a;
A(int a) : m_a(a) {}
};
struct B {
A m_a;
int m_b;
B(int a, int b) : m_a(a), m_b(b) {}
};
Or using your code:
#include <cstdio>
class myClassA{
public:
myClassA(){
printf("myClassTwo ctor");
}
void doSomething(){ printf("myClassA did something\r\n");}
};
class myClassB{
public:
myClassB(int i) : threeMyI(i) {
printf("myClassA ctor got %d\r\n",i);
}
private:
int threeMyI;
};
class myClassC{
public:
myClassC() : instanceA(), instanceB(20) {
printf("C ctor without params\r\n");
}
myClassA instanceA;
myClassB instanceB;
};
int main()
{
myClassA a;
myClassB b(10);
myClassC c;
}
Live demo
From what I have understand, it seems that you want to use a default instantiation for your private attribute instanceB. In that case, what you are proposing is not legal, default input parameters should be set as followed
myClassC() : instanceB(29) { // mind the ":" character
printf("C ctor without params\r\n");
}
This will have the effect to call the constructor of myClassB to instantiate your private attribute instanceB with relevant default parameter.
I've got a class A (from a library over which I have no control) with a private copy constructor and a clone method, and a class B derived from A. I would like to implement clone for B as well.
The naive approach
#include <memory>
class A { // I have no control here
public:
A(int a) {};
std::shared_ptr<A>
clone() const
{
return std::shared_ptr<A>(new A(*this));
}
private:
A(const A & a) {};
};
class B: public A {
public:
B(int data, int extraData):
A(data),
extraData_(extraData)
{
}
std::shared_ptr<B>
clone() const
{
return std::shared_ptr<B>(new B(*this));
}
private:
int extraData_;
};
int main() {
A a(1);
}
however, fails, since the copy constructor of A is private:
main.cpp: In member function ‘std::shared_ptr<B> B::clone() const’:
main.cpp:27:42: error: use of deleted function ‘B::B(const B&)’
return std::shared_ptr<B>(new B(*this));
^
main.cpp:17:7: note: ‘B::B(const B&)’ is implicitly deleted because the default definition would be ill-formed:
class B: public A {
^
main.cpp:14:5: error: ‘A::A(const A&)’ is private
A(const A & a) {};
^
main.cpp:17:7: error: within this context
class B: public A {
There might a way to make use of A::clone() for B::clone(), but I'm not sure how this would work exactly. Any hints?
I presume it's a typo that your B has no public members at all,
and that you're missing a public: before the definition of B::B(int,int).
The author of the class represented by your A apparently wants it to be
cloneable but not copy constructible. That would suggest he or she wants all
instances to live on the heap. But contrariwise, there's the public
constructor A::A(int). Are you sure you are right about that?
It's plausible to suppose that the class can reveal enough information
about a given instance to constitute another instance. E.g., putting
a little more flesh on A:
class A {
public:
A(int a)
: data_(a){};
std::shared_ptr<A>
clone() const
{
return std::shared_ptr<A>(new A(*this));
}
int data() const {
return data_;
}
private:
A(const A & a) {};
int data_;
};
And if that is true, then the public constructor would render it merely
inconvenient to circumvent the private, undefined copy constructor:
A a0(1);
A a1{a0.data()}; // Inconvenient copy construction
So I'm less than confident that A faithfully represents the problem
class. Taking it at face value, however, the question you need to answer
is: Can you even inconveniently copy construct an A?
If not then you're stuck. If so, then you can use inconvenient copy
construction of A to expressly define a conventional copy constructor for B,
which is all you need. E.g.
class B: public A {
public:
B(B const & other)
: A(other.data()),extraData_(other.extraData_){}
B(int data, int extraData):
A(data),
extraData_(extraData)
{
}
std::shared_ptr<B>
clone() const
{
return std::shared_ptr<B>(new B(*this));
}
int extradata() const {
return extraData_;
}
private:
int extraData_;
};
#include <iostream>
int main()
{
B b(1,2);
std::shared_ptr<B> pb = b.clone();
std::cout << pb->data() << std::endl;
std::cout << pb->extradata() << std::endl;
return 0;
}
You need to make the copy-constructor of A protected so that the derived class could use it:
protected:
A(const A & a) { /*...*/ }
Hope that helps.
The reason the default definition of B's copy constructor is ill-formed is because - if it was permitted - it would invoke the private (therefore inaccessible to B) and not defined copy constructor of A.
Make A's copy constructor either protected or public, so it is accessible to B. Another (really bad) option is to declare class B as a friend of A. All possibilities would also require you to provide a definition for A's copy constructor.
In the below code I have defined an explicit copy constructor in the derived class. I have also written my own copy constructor in the base class.
Primer says that the derived copy constructor must call the base one explicitly and that inherited members should be copied by the base class copy constructor only, but I copied the inherited members in the derived class copy constructor and it is working fine. How is this possible?
Also how do I explicitly call the base class copy constructor inside the derived class copy constructor? Primer says base(object), but I am confused how the syntax differentiates between normal constructor call and copy constructor call.
Thanks in advance.
#include<stdafx.h>
#include<iostream>
using namespace std;
class A
{
public:
int a;
A()
{
a = 7;
}
A(int m): a(m)
{
}
};
class B : public A
{
public:
int b;
B()
{
b = 9;
}
B(int m, int n): A(m), b(n)
{
}
B(B& x)
{
a = x.a;
b = x.b;
}
void show()
{
cout << a << "\t" << b << endl;
}
};
int main()
{
B x;
x = B(50, 100);
B y(x);
y.show();
return 0;
}
copy constructor is when you have another Object passed to your constructor:
class A() {
private:
int a;
public:
//this is an empty constructor (or default constructor)
A() : a(0) {};
//this is a constructor with parameters
A(const int& anotherInt) : a(anotherInt) {};
//this is a copy constructor
A(const A& anotherObj) : a(anotherObj.a) {};
}
for a derived class
class B : public A {
private:
int b;
public:
//this is the default constructor
B() : A(), b() {};
//equivalent to this one
B() {};
//this is a constructor with parameters
// note that A is initialized through the class A.
B(const int& pa, const int& pb) : A(pa), b(pb) {}
//for the copy constructor
B(const B& ob) : A(ob), b(ob.b) {}
}
How somebody else wrote here:
How to call base class copy constructor from a derived class copy constructor?
I would write the copy constructor like this instead how it was written by macmac:
B(const B& x) : A(x) , b(x.b)
{
}
To call the copy constructor of the base A you simply call it passing the derived B object A(B), is not neccessary to specify B.a.
EDIT: macmac edited his answere in the correct way, now his answere is better then mine.
#include <iostream>
#include <string>
using namespace std;
class A
{
public:
A() { i=1; j=2;};
A (A &obj) { i= obj.i+100; j= obj.j+100;};
int i;
int j;
};
class B:public A
{
public:
B():A() {i=10; j=20; k=30;};
B(A &obj) { A::A(obj); k=10000; };//
int k;
};
int main()
{
A dog;
B mouse(dog);
cout<<mouse.i<<endl;
cout<<mouse.k<<endl;
return 0;
}
I try to write a copy constructor for the derived class that takes advantage of the copy constructor for the base class. I expect that mouse.i should be 101, but in fact the compiling result is 1. The value for mouse.k is 10000, which is expected. I was wondering what's wrong with my code.
In this constructor:
B(A &obj) { A::A(obj); k=10000; };
A::A(obj); does not initialise the base sub-object; instead, it creates a local object also called obj. It's equivalent to A::A obj;, which is equivalant to A obj;. [UPDATE: or possibly it does something else, or possibly it's ill-formed - in any event, it's wrong.]
You want to use an initialiser list:
B(A & obj) : A(obj), k(10000) {}
Also, you almost certainly want the constructor parameters to be A const &, to allow construction from constant objects or temporaries.
You must use the initialization list to call the parent's constructor (and you should do it for all other members also):
B(A const& obj) : A(obj), k(10000) {}
Additionally, when copying you do not modify the original object, so you should take a const reference to it. That will allow you to copy from constant objects (or through constant references), improving const-correctness.
You should initialize the base class like this:
B(A &obj):A(obj) { k=10000; }
(more on this at What are the rules for calling the superclass constructor?). And a side-note: use const for copy constructor arguments:
A (const A &obj) {...}
EDIT:
The preferred way to initialize instance members is through an initialization list, so your ctor will look like
B(A &obj):A(obj), k(10000) { }
#include <iostream>
#include <string>
using namespace std;
class A
{
public:
A()
{
i=1;
j=2;
}
A (A &obj)
{
i= obj.i+100;
j= obj.j+100;
}
int i;
int j;
};
class B:public A
{
public:
B():A() {i=10; j=20; k=30;}
B(A &obj)
:A(obj)
{
//A::A(obj);
k=10000;
}//
int k;
};
int main()
{
A dog;
B mouse(dog);
cout<<mouse.i<<endl;
cout<<mouse.k<<endl;
return 0;
}
This work for me
B(A &obj)
{
A::A(obj)
}
Is illegal on gcc compiler
I'm trying to set up a copy constructor and i'm getting this error
class Class1{
public:
int get_data();
void set_data(int);
private:
int d;
};
int Class1::get_data(){
return d;
}
void Class1::set_data(int data){
d = data;
}
class Class2 : public Class1{
Class2(const Class2&);
};
Class2::Class2(const Class2 &c2) : Class1(){
set_data(c2.set_data());
}
whats a solution to this problem. i read some of the previous questions and i understand why this is happening. but making set_data() const is not an option.
whats the accepted approach for copy constructors?
thanks,
You could just write a constructor for Class1 taking an int parameter:
class Class1 {
explicit Class1 (int i) : d (i) {}
// as before
};
class Class2 : public Class1 {
Class2 (Class2 const & c2) : Class1 (c2.get_data ()) {}
};
However, the default copy constructor should be enought here (i.e. you don't need to write your own, the compiler will do it for you).
Generally speaking, you should use initialisation lists:
http://www.parashift.com/c++-faq-lite/ctors.html
in the constructors (read the whole entry in the faq)
Edit: You forgot the 'const' qualifier for your get_data function.
Don't you want:
set_data(c2.get_data());
(and make the Class1::get_data() member function const)?
But you really should be using constructor initialization lists:
Class2::Class2(const Class2 &c2)
: Class1(c2)
{
}
This code uses the compiler-generated default copy constructor for Class1. In many cases you shouldn't use the default copy constructor or copy-assign operator overload, but here it's fine because the sole data member of Class1 is an int object.
In fact, you could even rely on the compiler-generated default copy constructor for Class2.
EDIT: Here is some example code:
#include <iostream>
class Class1{
public:
Class1() : d(0) { } // Provide a no-arg constructor to initialize `d`
int get_data() const; // Class1::get_data() is `const` because it does not change the `Class1` object.
void set_data(int);
private:
int d;
};
int Class1::get_data() const{
return d;
}
void Class1::set_data(int data){
d = data;
}
class Class2 : public Class1{
public:
Class2();
};
Class2::Class2()
: Class1()
{
}
int main() {
Class2 other_c2;
other_c2.set_data(14);
Class2 c2(other_c2);
std::cout << c2.get_data() << '\n';
}
http://codepad.org/jlplTYrH