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.
Related
I am trying to create a base and a derived class with a const member that has to be initialized:
class baseClan
{
public:
baseClan(const string firstName)
:
fullName(createFullName(firstName))
{}
private:
const string lastName = "Smith";
const string fullName;
virtual const string createFullName(string firstName) { return firstName + " " + lastName ; }
}
How do I implement the derived class so that it can use a differently implemented createFullName? I am looking at this link
https://isocpp.org/wiki/faq/strange-inheritance#calling-virtuals-from-ctor-idiom
but it seems like I'm stuck between a rock and a hard place: the first approach it proposes (using init) is not applicable to initialization list; while in the second approach it is explicitly stated that it cannot handle the case where we need to access the instance data declared in Derived.
Calling virtual functions from a constructor or destructor is dangerous and should be avoided whenever possible. All C++ implementations should call the version of the function defined at the level of the hierarchy in the current constructor and no further.
Virtual functions in the constructors work differently. When creating an object of an derived class, the object of the base class is created first, which means that the derived class has not yet been created and the virtual function has not yet been overrided.
I think that all possible approaches to this problem are already described by the link that you provided (C++ FAQ). But I highly recommend rethinking your code.
You can apply a slightly different approach. You can make base constructor to accept parameters to initialize data fields, and then in derived class you pass the necessary arguments (even, perhaps, from virtual functions) to the base constructor using the initialization list. For example:
class A {
public:
A(int a, int b) : a_(a), b_(b) { }
virtual int getA() const = 0;
virtual int getB() const = 0;
void print() { cout << a_ << ' ' << b_ << endl; }
private:
const int a_ = 0;
const int b_ = 0;
};
class B : public A {
public:
B() : A(getA(), getB()) { }
int getA() const override { return 1; }
int getB() const override { return 2; }
};
int main() {
B b;
b.print();
return 0;
}
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()
{}
};
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 class which uses a class of base pointers to derived objects, so I need to have my own desructor for deleting the vector's elements and custom copy and assignment funcitons. I'm not entirely sure about the preferred way of implementing a structure like below and writing the right copy and assignment constructors and destructors for it. May I ask you to guide me? I've read a lot and searched but I'm still not sure.
class Base
{
public:
Base();
~virtual Base();
int a;
int type; // Derived1 or Derived2
std::string b;
...
}
class Derived1 : public Base
{
public:
Derived1();
Derived1(const Base* a);
virtual ~Derived1();
}
class Derived1
{
Derived1::Derived1(const Base *a) : Base(a)
{
}
}
class Derived2 : public Base
{
public:
Derived2();
Derived2(const Base* a);
virtual ~Derived2();
std::string d1;
std::string d2;
int d3;
}
class Derived2
{
Derived2::Derived2(const Base *a) : Base(a) {
this->d1 = ((Derived2*)a)->d1;
this->d2 = ((Derived2*)a)->d2;
this->d3 = ((Derived2*)a)->d3;
}
}
class A
{
public:
A();
~A();
A(const A& a);
A& operator = (const A& a);
std::string someString;
std::vector<Base*> vect;
}
A::~A() {
std::vector<Base*>::iterator it = vect.begin();
while (it != vect.end()) {
delete (*it);
it++;
}
A::A(const A &a)
{
someString = a.someString;
for(std::size_t i = 0; i < a.vect.size(); ++i {
someString = a.someString;
Base* base = a.vect.at(i);
if(base->type == base::TypeD1) {
base = new Derived1( a.vect.at(i) );
vect.push_back( base );
}
else {
base = new Derived2( a.vect.at(i) );
vect.push_back( base );
}
}
}
Your loop in the destructor is fine in practice, and is the
usual solution. Formally, it is undefined behavior, since you
are leaving objects in the vector (pointers to deleted objects)
which aren't copiable, but in practice: the vector won't copy
them unless you resize it to something bigger, or insert or
erase on it. If you really want to avoid the undefined
behavior:
for ( auto current = vect.begin(); current != vect.end(); ++ current ) {
Base* tmp = *it;
*it = nullptr;
delete tmp;
}
But this is one case where I probably wouldn't bother (and
I tend to be more sensitive to undefined behavior than most).
First, do you actually need to copy and assign objects of type A? If no, the simple solution is:
class A
{
public:
A();
~A();
A(const A&) = delete;
A(A&&) = default;
A& operator=(const A&) = delete;
A& operator=(A&&) = default;
// ...
};
If yes, then you want some polymorphic way of copying the elements of the vector. (Any time at all you have if (b->type == Base::TypeD1) { do_this(); } else { do_that(); }, stop and think if it would make sense to add a virtual function for do_this/do_that. The else-if-heimer's way doesn't allow for future new derived classes; the virtual way does.)
class Base
{
public:
// ...
virtual Base* clone() const = 0;
// ...
};
class Derived1 : public Base
{
public:
virtual Derived1* clone() const;
};
Derived1* Derived1::clone() const {
return new Derived1(*this);
}
The copy assignment operator of A will need to destroy the old contents of the lhs, just like the destructor, and then copy the new contents over, just like the copy constructor. So let's put those two operations in private functions:
class A
{
public:
A();
~A();
A(const A&);
A(A&&) = default;
A& operator=(const A&);
A& operator=(A&&) = default;
// ...
private:
void destroy_contents();
void copy_from(const std::vector<Base*>& v);
};
void A::destroy_contents() {
std::vector<Base*>::iterator it = vect.begin();
while (it != vect.end()) {
delete (*it);
++it;
}
vect.clear();
}
void A::copy_from(const std::vector<Base*>& v) {
std::vector<Base*>::const_iterator it = v.begin();
while (it != v.end()) {
vect.push_back((*v)->clone());
++it;
}
}
A::~A() { destroy_contents(); }
A::A(const A& a) :
someString(a.someString),
vect()
{
copy_from(a.vect);
}
A& A::operator=(const A& a) {
if (this != &a) {
someString = a.someString;
destroy_contents();
copy_from(a.vect);
}
return *this;
}
If you have a vector of any pointer type, the vector does not know anything about the type behind the pointer, nor does it care: The vector operates on the pointers only, copying them to a new location if need be, but never even touching the objects themselves. As such, it is your responsibility to destroy the objects themselves.
As James Kanze points out, there is a slight danger of undefined behavior when handling invalidated pointers. However, since the vector is not used in any way after deleting the objects it holds, no undefined behavior is invoked in the code you've given (the vector won't need to reallocate its memory so it won't need to assign invalidated pointers, and destruction of pointers is a noop). As such, your destructor of class A is perfectly fine.
The copy constructor of class A, however, is unnecessarily complicated and an ample source of errors (it needs to be updated whenever a new derived class is defined!). The best way to do this is to use a clone() function:
class Base {
public:
//...
virtual Base* clone() const = 0; //Returns a new copy of the object. Pure virtual if the Base class is abstract.
};
class Derived1 : public Base {
public:
Derived1(const Derived& a);
virtual Derived* clone() const {
return new Derived1(*this);
}
};
If you make clone() pure virtual in the base class, you have the guarantee that your compiler will complain if you forget to implement it in any derived class. With that, the copy constructor of class A is next to trivial:
A::A(const A &a) {
someString = a.someString;
for(std::size_t i = 0; i < a.vect.size(); ++i {
vect.push_back(a.vect[i]->clone());
}
}
I have wrote a program that use inheritance, everything is OK but an error that I think shouldn't not be here naturally.
here is my program:
class A
{
protected:
int x;
public:
A(){};
~A(){};
A* operator=(const A* other)
{
this->x = other->x;
return this;
}
};
class B : public A
{
public:
B() : A(){};
~B(){};
};
class C
{
protected:
A *a;
public:
C(const A* other){ *(this->a) = other; };
};
int main()
{
B *b = new B();
C *c = new C(b);
return 0;
}
It produces an execution time error in the statement 'this->x = other->x;'.
What about this?
*(this->a) is undefined behavior, because this->a wasn't initialized - it's just a dangling pointer.
You can use a = new A; *a = other (the this-> in this case is redundant), but this isn't the proper C++ way - you should use RAII (look it up) - you wouldn't need destructors, assignment operators or copy constructors if you did.
Also, operator = typically returns *this by reference.
I like Luchian's answer but there is still some places to enhanced in your code, you may still encounter some undefined behavior in your code before you fix other potential bugs.
class A
{
protected:
int x;
public:
A():x(0){} // should always initialize x in constructor
virtual ~A()=0 {} // as A is a base case, ~A must be virtual
A& operator=(const A& other) // a reference will be more practical better?
{
this->x = other.x;
return *this;
}
};
If you don't want to make B object as well which means B is serviced as a base class, you should make its destructor virtual as well, even make it pure virtual.
class B : public A
{
public:
B() : A(){}
virtual ~B(){} =0
{ }
};
*(this->a) = other; is answered by Luchian already. In your code, if you want to keep a copy of pointer which points to A, you can simply initialize a_ptr in member initialize list
see below demo code:
class C
{
protected:
A *a_ptr;
public:
C(A* other):a_ptr(other){ }
};
Finally come to your main function, if b,c are only used in main function, when program finishes, system will claim dynamic allocated memory back, but if you use a,b in a loop, you need to delete them manually.