I have two classes:
class NonCopyable {
private:
int key;
protected:
NonCopyable(const NonCopyable&) = delete;
NonCopyable& operator = (const NonCopyable &) = delete;
};
class Derived : public NonCopyable {
private:
std::vector<int> numbers;
float f;
int* ptr;
public:
Derived() : f(5.0f), ptr(nullptr) {}
~Derived();
};
Now, I'd like to reinitialize all the values in the Derived class and call the appropriate destructors. That is, the NonCopyable class should not be touched, but the Derived class should be changed as if it was newly initialized.
What is the simplest way of achieving this goal? I am trying to avoid making a member function which manually reinitializes every member variable.
Clearly, I can not use the following approach:
Derived d;
// [...] many changes to d
d = Derived();
because the copy constructor is deleted from the NonCopyable class and the fact that it would change the member variables of NonCopyable had this not been the case.
It becomes much easier if you move your private data to a separate aggregate:
struct DerivedData {
std::vector<int> numbers;
float f = 5.0;
int* ptr = nullptr;
};
class Derived : public NonCopyable {
DerivedData data;
public:
~Derived();
void reset() { data = DerivedData(); }
};
Related
Providing the simple implementation of a Singleton class below. It is possible for anybody to call the destructor as long as s/he has the reference to the singleInstance.
class SomeClass {
public: /** Singleton **/
static SomeClass &instance() {
static SomeClass singleInstance;
return singleInstance;
};
private:
SomeClass() = default;
SomeClass(const SomeClass&) = delete;
SomeClass &operator=(const SomeClass&) = delete;
};
To prevent such a nonsense operation, should we declare the destructor of Singleton classes in a private context?
class SomeClass {
// ... same above
private:
~SomeClass() {}
};
The problem exists also for the heap-allocated Singleton instances. Consider the implementation below.
class SomeClass {
public: /** Singleton **/
static SomeClass &instance() {
static SomeClass *singleInstance = nullptr;
if(!singleInstance) {
singleInstance = new SomeClass;
}
return *singleInstance;
};
private:
SomeClass() = default;
SomeClass(const SomeClass&) = delete;
SomeClass &operator=(const SomeClass&) = delete;
// ~SomeClass() {}
};
int main()
{
SomeClass *const ptr = &SomeClass::instance();
delete ptr; // Compiles if destructor isn't private and vice versa
return 0;
}
Should we declare the desctructor of a Singleton class as private?
Yes.
Sidenote: Singleton pattern is rarely necessary, an using it unnecessarily is a common anti pattern.
I have the following situation:
Factory class implementation:
class FactoryClassA {
public:
FactoryClassA(){};
~FactoryClassA(){};
ClassA create(double a, double b) {
return ClassA;
};
};
ClassA implementation:
class ClassA {
friend class FactoryClassA
~FactoryClassA() {}
private:
ClassA(double a = 0, double b = 0)
{
a(a),
b(b)
};
double a;
double b;
};
OtherClass implementation:
class OtherClass {
public:
OtherClass() {
ClassFactory myClassAFactory;
aClassA = myClassAFactory.create();
}
~OtherClass() {};
private:
aClassA;
};
Unfortunately, this does not work. Because in the (empty) member initializer list of OtherClass, the empty constructor of ClassA is called, which does not exist.
The reason why I made the constructor of ClassA private, is that I want the user to only create objects of ClassA through the FactoryClassA.
First of all, create() should have a return type:
ClassA create(double a, double b) {
return {a, b};
}
I am not going through all the other syntactic bugs. Please fix them, because others might find your question when they search for answers. Please make it easy for them to understand your question.
This has to be in your code after ClassA has been defined, because the compiler has to know the size of a ClassA object as well as the constructor to use.
Second, just initialize your members before the constructor body:
OtherClass() :
aClassA{ClassFactory{}.create(0.0, 0.0)}
{}
You might prefer to have create() as a static member function of ClassFactory. Then the OtherClass constructor looks like this:
OtherClass() :
aClassA{ClassFactory::create(0.0, 0.0)}
{}
That is more intuitive.
This code is full of small errors, that make it unuseable. First syntax for member initialization for a class is :
class A {
A(x, y): m_a(x) { ... }
...
}
and class declaration are statements so they need the final ;
Next, the dtor for a class must be public if you want to be able to use temporary objects.
The default values should not be in ClassA ctor but on create factory method.
Finally, you should use a static factory in OtherClass, no need to create a new factory for each object.
Code becomes:
class FactoryClassA;
class ClassA {
public:
friend class FactoryClassA;
~ClassA(){}
private:
ClassA(double a, double b):a(a),b(b){}
double a;
double b;
};
class FactoryClassA {
public:
FactoryClassA(){}
~FactoryClassA(){}
ClassA create(double a = 0, double b = 0) {
return ClassA(a, b);
}
};
class OtherClass {
public:
OtherClass(): aClassA(myClassAFactory.create()){}
~OtherClass(){}
private:
static FactoryClassA myClassAFactory;
ClassA aClassA;
};
FactoryClassA OtherClass::myClassAFactory;
Not far from original one, but this ones compiles...
I want to have a derived class which has a default constructor that initializes the inheirited members.
Why can I do this
class base{
protected:
int data;
};
class derived: public base{
public:
derived(){ //note
data = 42;
}
};
int main(){
derived d();
}
But not this
class base{
protected:
int data;
};
class derived: public base{
public:
derived(): //note
data(42){}
};
int main(){
derived d();
}
error: class ‘derived’ does not have any field named ‘data’
An object can only be initialized once. (The exception is if you initialize it and then destroy it; then you can initialize it again later.)
If you could do what you're trying to do, then base::data could potentially be initialized twice. Some constructor of base might initialize it (although in your particular case it doesn't) and then the derived constructor would be initializing it, potentially for a second time. To prevent this, the language only allows a constructor to initialize its own class's members.
Initialization is distinct from assignment. Assigning to data is no problem: you can only initialize data once but you can assign to it as many times as you want.
You might want to write a constructor for base that takes a value for data.
class base{
protected:
int data;
base(int data): data(data) {}
};
class derived: public base{
public:
derived(): base(42) {}
};
int main(){
derived d{}; // note: use curly braces to avoid declaring a function
}
You need a base class constructor for this job. You can look for more explanation here -
Initialize parent's protected members with initialization list (C++)
I have a base class with a member variable (preferably private) and I need to enforce derived classes to initialize it with a value based on their implementation; much like a pure virtual function.
To clarify, I want to declare a member in Base, have derived classes initialize it, and if they don't they get a compiler error. In the following code, I declared default constructor of Base to be protected. Then declared default constructor of Derived to be private.
class Base {
private:
int _size;
protected:
Base(){}
/* pure virtual methods */
public:
Base(int size) : _size(size){} // must enforce derived to call this.
virtual ~Base(){}
/* more pure virtual methods */
};
class Derived : public Base {
private:
Derived() {}
public:
Derived(int size) : Base(size) {
//Base::Base(size);
}
};
int main()
{
Derived* d1 = new Derived(); // throws an error as needed:
// "Cannot access private member declared in class 'Derived'"
Derived* d2 = new Derived; // throws an error as needed:
// "Cannot access private member declared in class 'Derived'"
Derived* d3 = new Derived(5); // works as needed
return 0;
}
The problem with the above code is that if another definition of Derived doesn't hide the default constructor. I'm still stuck with an uninitialized Base::_size.
I don't know if there is another way to go about this other than inheritance, because I still need derived classes to implement their own behavior for several methods declared in Base.
Any pointers are appreciated.
After the confusion about calling a base class ctor and default ctors, maybe the solution is just to not have a default ctor in Base?
class Base {
private:
int _size;
public:
// no default ctor
Base(int size) : _size(size) {} // must enforce derived to call this.
virtual ~Base(){}
/* more pure virtual methods */
};
class Derived : public Base {
public:
// no default ctor
Derived(int size) : Base(size){
}
// examplary default ctor:
//Derived() : Base(42) {}
};
int main()
{
Derived d1; // error: no default ctor
Derived* d2 = new Derived; // same, but why use the free store?
Derived d3(5); // works as needed
Derived* d4 = new Derived(5); // same, but why use the free store?
return 0;
}
To be explicit about not having a default ctor, one could use
class Base {
/* ... */
Base() = delete;
/* ... */
};
Use a constructor
class Base1 {
protected:
Base1(int forward) {
thingYouWantToHide = forward;
}
private:
int thingYouWantToHide;
};
class Derived1: public Base1 {
public:
Derived1(): Base1(5) {}
};
class Base2 {
private:
int value;
protected:
Base2() {
value = calledToGet();
}
virtual int calledToGet() = 0;
virtual ~Base2() {} //shut compiler warnings up
};
class Derived2: public Base2 {
virtual int calledToGet() {
return 5;
}
};
int main(int,char**) {
Derived1 a;
Derived2 b;
return 0;
}
You may think Derived2 will work, but remember Derived2 is not constructed until Base2 is, so that virtual is an undefined reference when Base2 is being constructed.
You should use the first case, type-traits if it is a constant (static const) or fundamental to the type.
Suppose I have a class with a factory method
class A {
public:
static A* newA()
{
// Some code, logging, ...
return new A();
}
}
Is it possible to prevent the instantiation of an object of this class with a new, so that factory method is the only method to create an instance of the object?
Sure; just make the constructor private (protected if this is a base class):
class A {
public:
static A* newA()
{
// Some code, logging, ...
return new A();
}
private:
A() {} // Default constructor
};
You should make the copy constructor private/protected as well, if required.
And as always, you should strongly consider returning a smart pointer rather than a raw pointer, in order to simplify memory management issues.
You may also want to make the copy constructor private as well or with new C++11 syntax you can explicitly tell the compiler to not copy it and make the default constructor private with something like this:
struct NonCopyable {
NonCopyable & operator=(const NonCopyable&) = delete;
NonCopyable(const NonCopyable&) = delete;
NonCopyable() = default;
};
class A : NonCopyable {
public:
static std::shared_ptr<A> newA()
{
// Some code, logging, ...
return std::make_shared<A>();
}
private:
A() {} // Default constructor
};
The C++03 way was usually something like this:
class A {
public:
static A* newA()
{
// Some code, logging, ...
return new A();
}
private:
A() {} // no outsider default constructor
A(const A& rhs); // no copy
A& operator=(const A& rhs); // no assignment
};
int main()
{
A x; // C2248
A y(x); // C2248
x = y; // C2248
A* p = A::newA(); // OK
std::cin.get();
return 0;
}