I have a class B which has a member that is a pointer to an object of a A class. When using copy constructor on an object of type A, it is copied but the member variable is not.
Is there any way to copy an A object and to automatically make a copy of its B member?
The following code shows the problem I'm triying to explain:
class A
{
public:
A(char t_name)
{
name = t_name;
}
~A()
{
}
char name;
};
class B
{
public:
A* attribute;
B()
{
attribute = new A('1');
}
~B()
{}
};
int main()
{
B* b_variable = new B;
B* b_copy = new B(*b_variable);
return 0;
}
When using copy constructor on an object of type A, it is copied but the member variable is not.
Your code never calls any copy constructor in class A.
Your code calls a copy constructor in class B and it does exactly what is is supposed to, i.e. copies the value of attribute which is a pointer to a class A object.
In other words - after executing your code, you have two instances of class B and one class A instance. In the two class B instances attribute points to the same class A instance.
This is (most likely) not what you want.
As many already has pointed out (e.g. see #lostbard answer), you'll need a copy constructor in class B to do a deep-copy. A deep-copy is needed because class B have a pointer member.
Also you should do some clean up in class B destructor and in main.
#include <iostream>
using namespace std;
class A
{
public:
A(char t_name)
{
name = t_name;
}
~A()
{
}
char name;
};
class B
{
public:
A* attribute;
B()
{
attribute = new A('1');
}
/** Copy constructor */
B(const B ©)
{
// Make a new instance of class A
attribute = new A(*copy.attribute);
}
/** Assignment operator */
B& operator= (const B& other)
{
// Delete the existing class A instance
delete attribute;
// and create a new as a copy of other.attribute
attribute = new A(*other.attribute);
}
~B()
{
// Delete the class A instance
delete attribute;
}
};
int main()
{
B* b_variable = new B;
B* b_copy = new B(*b_variable);
// Delete the two class B instances
delete b_variable;
delete b_copy;
return 0;
}
There is no need for a copy constructor in class A. The default generated will do as Class A has no pointer members.
EDIT
As pointed out by #Slava you should always implement a assignment operator when you make a copy constructor (rule of three) so I added it to the code above.
Some like the rule of three to be the rule of five so it also include move. Read more here: https://en.wikipedia.org/wiki/Rule_of_three_(C%2B%2B_programming)
While there are many solutions, I'd bet sooner-or-later you'll end up with implementing the usual virtual a.clone();. That works flawless when you'll have derived classes of A (which is more-or-less the only legitimate reason why you're keeping A as a pointer to a heap-allocated object and not as a value member :) ).
Note that, when you're implementing clone() in your hierarchy, that C++ supports covariant pointer return types. Thus, if base has a virtual that returns e.g. Clonable*, then A's same method can return A* and A's descendant ADerived can return ADerived*. Feel free to understand 'can' as 'should' for the case of clone().
Create a copy constructor for A and for B:
class A
{
public:
A(char t_name)
{
name = t_name;
}
A(const A& copy)
{
name = copy.name;
}
~A()
{
}
char name;
};
class B
{
public:
A* attribute;
B()
{
attribute = new A('1');
}
B(const B ©)
{
attribute = new A(*copy.attribute);
}
~B()
{}
};
Related
I have a task where I need to do the following.
I have 3 classes with A links to many B association A->*B->*C
A: Contains only -iA_ : int
B: Contains only -iB_ : int
C: Contains only -IC_ : int
The task is:
Implement the necessary codefor all classes so that A contains a copy structure for deep copies. Container type list. Setter and getter are not necessary!
Further constructors and destructors are not necessary!
If you use default implementations you have to justify this.
So I have implemented it is this correct?
class C
{
private:
int iC_;
}
class B
{
private:
int iB_;
std::list<C*> CList_;
public:
B(std::list<C*> CList) : CList_(CList)
{
}
}
class A
{
private:
int iA_;
std::list<B*> BList_;
public:
A(std::list<B*> BList) : BList_(BList)
{
}
A(const A& crA)
{
iA_ = crA.iA_;
}
}
Unfortunately, your code is not correct yet. In order to create deep copies of a class that contains pointers, you need to copy the objects that those pointers point to as well. Here is a simple example with just A and B:
class B
{
private:
int iB_;
public:
// you will not be able to default this in your code
B(const B& other) = default;
};
class A
{
private:
int iA_;
vector<B*> BList_;
public:
A(const A& other) : iA_{other.iA_}, BList_{}
{
// fill up the BList_ with copies of other's BList_ items
for (auto b : other.BList_) {
// call B's copy constructor
B* copyPtr = new B{*b};
BList_.push_back(copyPtr);
}
}
A& operator=(const A& other)
{
iA_ = other.iA_;
// destroy all the current items in BList_
while (!BList_.empty()) { delete BList_.pop_back(); }
// fill up the BList_ with copies of other's BList_ items
for (auto b : other.BList_) {
// call B's copy constructor
B* copyPtr = new B{*b};
BList_.push_back(copyPtr);
}
}
~A()
{
// destroy all the current items in BList_
while (!BList_.empty()) { delete BList_.pop_back(); }
}
};
With your code, you will need to implement a similar thing with B's copy constructor as well to make sure it makes copies of everything in CList_, only then will you have a true deepcopy.
Edit: As #Alan Birtles noted, in such an implementation you should also define the copy assignment operator and destructor to prevent memory leaks.
I need to delay the constructor call, so I can initialize the value that should be passed to the constructor. I have written a short and very simplified example.
class A
{
private:
ObjectA* _ptr;
public:
A(ObjectA*);
};
class B
{
private:
A object; // The constructor seems to be called here?
ObjectA* obj;
public:
B();
};
A::A(ObjectA* ptr)
{
this->_ptr = ptr;
}
B::B()
{
obj = new ObjectA();
object(obj); // I want to call the 'A' constructor here, after initializing of 'obj'.
}
Is it possible?
No, you cannot defer a construction of a value member. You can use a pointer instead of a direct value but that's no solution for your problem.
The proper solution for your problem is using initialization list:
B::B ( ) : obj(new ObjectA), object(obj) {}
Also, you have to put obj before object in class B:
class B
{
private:
ObjectA *obj;
A object;
public:
B ( );
}
The reason for this is that, when a constructor is called, all of the objects members must be properly constructed and initialized. This is done using their default constructor.
The reason for reordering the class members is that the initializers of the members are called in the order they are declared in the class not in the order of their appearence in the initialization list.
Here is a solution I would use.
class B
{
private:
char m_aBytes[sizeof(A)];
A& getA () { return *(A*)m_aBytes; }
public:
B ()
{
ObjectA* objA = new ObjectA ();
new (m_aBytes) (objA);
}
}
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.
Forgive me if this has already been asked, I didn't find any answers to my specific question.
I have a class in a library I'm making that I want certain classes to be able to create and destroy, and other classes to be able to access other public functions. Having a friend class is not what I want either as the friend class will get access to member variables and member functions which I don't want. I stumbled upon this idiom which almost works, except for the destructor since it can't take additional parameters. With that idiom, I get:
class B;
class A
{
public:
class LifecycleKey
{
private:
LifecycleKey() {}
friend class B;
};
A(LifecycleKey); // Now only class B can call this
// Other public functions
private:
~A(); // But how can I get class B to have access to this?
void somePrivateFunction();
// Members and other private functions
};
As alluded to in the above code, the solution doesn't allow only class B to have access to the destructor.
While none of the above issues are deal breakers by any stretch as I can always just make ctor and dtor public and just say "RTFM".
My question is:
Is there is some way to limit access to ctor and dtor to specific classes (but only the ctor and dtor) while adhering to more well known syntax (having stuff be on the stack if people want, destroying via delete , etc.)?
Any help is greatly appreciated!
SOLUTION
in A.h
class B;
class A
{
protected:
A() {}
virtual ~A() {}
A(const A&); // Implement if needed
A(A&&); // Implement if needed
public:
// Public functions
private:
void somePrivateFunction();
// Members and other private functions
};
in B.h
class B
{
public:
B();
~B();
const A* getA() const;
private:
A* m_a;
}
in B.cpp
namespace {
class DeletableA : public A {
public:
DeletableA() : A() {}
DeletableA(const DeletableA&); // Implement if needed
DeletableA(DeletableA&&); // Implement if needed
~DeletableA() {}
}
}
#include B.h
B::B() : m_a(new DeletableA()) {}
B::~B() { delete static_cast<DeletableA*>(m_a); }
const A* B::getA() const { return m_a; }
Alternatively, if the DeletableA class is needed in B.h or A.h (due to inlining, templating, or desire to have all class A related classes in A.h), it can be moved there with a "pass key" on the constructor so no other classes can create one. Even though the destructor will be exposed, no other class will ever get a DeletableA to delete.
Obviously this solution requires that class B know to make instances of Deletable A (or to make the class in general if it isn't exposed in A.h) and only store A* that are exposed via public functions, but, it is the most flexible set up that was suggested.
While still possible for some other class to make a subclass of class A (since class A isn't "final"), you can add another "pass key" to the constructor of A to prevent such behavior if you wish.
For the goal that class B should be the only one able to instantiate and destroy objects of class A:
For static and automatic variable, restricting access to the constructor is all that's needed, and you're already doing that.
For dynamically allocated object you can restrict access to its deallocation functions, operator delete, and operator delete[], and leave the destructor public. This prohibits other code than B from deleting objects.
For dynamically objects you can derive class A from an interface with protected virtual destructor or named self-destroy function, which has class B as friend. B can then destroy any dynamic A object by casting up to the interface that it has access to.
Code that explicitly calls the destructor deserves whatever it gets.
Remember, you're never building an impregnable defense against malicious code, you're just building a reasonable detection and compile time reporting of inadvertent incorrect use.
Use a mediator-class:
class mediator;
class A
{
/* Only for B via mediator */
A();
~A(); // But how can I get class B to have access to this?
friend class mediator;
/* Past this line the official interface */
public:
void somePrivateFunction();
protected:
private:
};
class B;
class mediator
{
static A* createA() { return new A{}; }
static void destroyA(const A* p) { delete p; }
// Add additional creators and such here
friend class B;
};
Thus, only the mediator, as part of the interface to B, gets full access.
BTW: Instead of restricting access to the dtor, you might get happier overloading new and delete and restricting access to them.
The advantage: Allocation on the stack is generally possible, if the variable is directly initialized without copying.
void* operator new(std::size_t);
void* operator new[](std::size_t);
void operator delete(void*);
void operator delete[](void*);
void operator delete(void*, std::size_t) noexcept;
void operator delete[](void*, std::size_t) noexcept;
use shared_ptr
class K{
public:
int x;
private:
~K(){};
K(){};
private:
friend class K_Creater;
friend class K_Deleter;
};
struct K_Deleter{ void operator()(K* p) { delete p; } };
struct K_Creater{
static shared_ptr<K> Create(){
return shared_ptr<K>(new K, K_Deleter() );
}
};
//K* p = new K; prohibited
shared_ptr<K> p = K_Creator::Create();
another answer is:
#include <iostream>
class A
{
public:
class Key
{
private:
Key(){
std::cout << "Key()" << std::endl;
}
~Key(){
std::cout << "~Key()" << std::endl;
}
friend class B;
};
A(Key key){
std::cout << "A(Key key)" << std::endl;
}
void seti(){ i_=0;}
private:
int i_;
};
class B{
public:
static void foo(){
A a{A::Key()};
A* pa = new A( A::Key() );
delete pa;
static A sa({});
}
};
int main(){
B::foo();
//A a{A::Key()}; prohibit
//A* pa = new A( A::Key() ); prohibit
//delete pa; prohibit
//static A sa({}); prohibit
return 0;
}
My take:
Any class/function that has access to the constructor should also have access to the destructor.
You should make ~A() public since A() is public. Since no other client except B can use the constructor, they won't have the need to use the destructor anyway.
You can further limit who can access the destructor by declaring away the copy and move constructors, and the new and delete operators.
Update
Making the destructor public and declaring away the copy and move constructors seems to address all of your concerns. You don't even need to declare away the new and delete operators or their array variants.
Here's what I think should meet most of your needs.
class B;
class PassKey
{
private:
PassKey() {}
~PassKey() {}
friend class B;
};
class A
{
public:
A(PassKey) {}
~A() {}
private:
// Declare away
A(A const&);
A(A&&);
};
Now, let's take a look at what B can have:
class B
{
public:
B() : a(PassKey()), ap(new A(PassKey())), ap2(new A(PassKey())) {}
~B() { delete ap; }
A const& getA() const {return a;}
A a;
A* ap;
std::shared_ptr<A> ap2;
};
It can have the following member data types:
Objects of type A.
Raw pointers to objects of type A.
Objects of type shared_ptr<A>.
Member functions of B can also create any of the above types of objects.
Other classes can't use objects of type A since they cannot construct one in any way. All the following attempts to use A in various forms fail.
struct C
{
C() : a(PassKey()) {} // Can't construct an instance of A
// since C doesn't have access to
// PassKey's constructor.
A a;
};
struct D
{
D() : a(new A(PassKey())) {} // Can't construct an instance of A
// since D doesn't have access to
// PassKey's constructor.
A* a;
};
struct E
{
E(A const& a) : ap(new A(a)) {} // Can't construct an instance of A
// since E doesn't have access to
// A's copy constructor.
A* ap;
};
class F
{
public:
F(A& a) : ap(new A(std::move(a))) {} // Can't construct an instance of A
// since F doesn't have access to
// A's move constructor.
A* ap;
};
I have a abstract base class that hold data, and I need allocate memory to these data, and the other problem is that derivate class has the = operator overloaded and copy constructor, I would like to know how Can I assure that in the derivate class copy the members data from abstract base class will be copied too, follows the code exemple:
class A {
public:
A(const char* v) {
value = new char[strlen(v)+1];
strncpy(value, v, strlen(v));
}
A(const A &a) {
value = new char[strlen(a.value)+1];
strncpy(value, a.value, strlen(a.value));
}
virtual ~A() {
delete[] value;
}
A& operator=(const A& a) {
value = new char[strlen(a.value)+1];
strncpy(value, a.value, strlen(a.value));
return *this;
}
const char* get() const {
return value;
}
virtual void do_some() = 0;
private:
char *value;
};
class B: public A {
public:
B(const char *v, const char *n) : A(v) {
name = new char[strlen(n)+1];
strncpy(name, n, strlen(n));
}
B(const B &b) : A(b) {
name = new char[strlen(b.name)+1];
strncpy(name, b.name, strlen(b.name));
}
~B() {
delete[] name;
}
B& operator=(const B& b) {
A::operator=(b);
name = new char[strlen(b.name)+1];
strncpy(name, b.name, strlen(b.name));
return *this;
}
const char *get() const {
return name;
}
void do_some() {
std::cout << name << std::endl;
}
private:
char *name;
};
My doubts is, in some C++'s books says that is not a good idea to overload the operator = and declare a copy constructor in abstract base class, so how can I declare a copy constructor and operator= in derivate class and assure that the base class was copied properly?
In my project if I don't use data members at the abstract base class, I have to declare some data members in all derivate class, of course that is more than one, so I designed the abstract class with data member, but I don't know if is the better way to do.
What you're doing is a little awkward, but technically fine (except for leaking memory by not deleting name and value in the assignment operator before new[]-ing it), however only if you have no plans for multiple inheritance. That gets a bit messy, and may be why whatever books you're referring to are warning against it, but you shouldn't be using multiple inheritance (in general, but especially) on classes with data members anyways.
You might want to try a different approach regardless. Consider using a protected helper function (or a few) in the base class to set its variables:
class A
{
public:
// ...
private:
char *value;
protected:
void set_value(const char *str)
{
delete[] value; // remember, deleting null does nothing
value = new char[strlen(str)+1];
strncpy(value, str, strlen(str)); // Also, why do you need strncpy?
// You'll get no null-terminator, which leads to major problems
// Consider just strcpy(value, str);
}
};
This way, you can set that value from any derived class, the functionality is still hidden from public use, and you don't have to write an assignment operator or copy constructor for an abstract class. Which, when you think about it, really doesn't make much sense, does it?
It also saves you from this:
A *a = new B;
B *b = new B;
(*a) = (*b); // ...with an assignment operator on A, this should compile.