Singleton Derived Class with multiple bases of non-default constructors - c++

I have a class derived from multiple base classes and I want to make it a singleton. Problem is the derived and base classes do not use default constructors and take arguments, so I'm confused how I can manage. I want to be able to pass the arguments to what would have been the constructor, but I only want possible to do once (I don't want it to be a setter). My only solution was a static bool value in the getInstance() member of the derived class.
Basic case:
//Singleton Derived Class with multiple bases of non-default constructors
class base1 {
public:
base1(int* value) :
val_{value} {;}
~base1();
private:
int val_;
}
class base2 {
public:
base2(int* value) :
val_{value} {;}
~base2();
private:
int val_;
}
class derived : public base1, public base2 {
public:
derived(int* value) :
base1{value}, //Base 1 constructor call
base2{value}, //Base 2 constructor call
val_{value} {;}
~derived();
private:
int val_;
}
//Creation
derived newDerived(&value);
Attempt to make it singleton-like?
//Lets make it a singleton
class base1 {
public:
base1(); //Can I pass the construtor anything?
~base1();
private:
int val_;
}
class base2 {
public:
base2(); //Can I pass the construtor anything?
~base2();
private:
int val_;
}
class derived : public base1, public base2 {
public:
static derived& getInstance(int* value) {
static bool init;
if (!init) {
base1::val_ = value;
base2::val_ = value;
init=true;
}
static derived instance;
return instance;
}
derived(int* value) {;}
~derived();
private:
derived(derived const&) = delete; //Copy construct
derived(derived&&) = delete; //Move construct
derived& operator=(derived const&) = delete;//Copy assign
derived& operator=(derived &&) = delete; //Move assign
int val_;
}
//Creation
derived::getInstance(&value);
I'm looking for some direction on how I should go about this, or maybe reasons I shouldn't do it at all? Thanks

Here you go. Instead of reference I am using pointer here. This is just an example hence I am not making this singleton as thread safe. Also declare a default constructor as private so that it can not be instantiate.
class base1 {
public:
base1(int* value) : val_(*value) {}
~base1() {};
private:
int val_;
};
class base2 {
public:
base2(int* value) :
val_(*value ) { }
~base2() {};
private:
int val_;
};
class derived : public base1, public base2 {
private:
derived(int* value) :
base1(value), //Base 1 constructor call
base2(value), //Base 2 constructor call
val_(*value) {}
~derived() {};
private:
int val_;
static derived* driv;
public:
static derived* getInstance(int* value);
};
derived* derived::driv = NULL;
derived* derived::getInstance(int* value)
{
if (driv == NULL)
{
driv = new derived(value);
}
return driv;
}

Related

Copy constructor for every derived class

Consider the following code. I want the convert function to work without defining the T(const Base&) copy constructor in every concrete derived type of Base.
It could be done in the intermediate class CRTP<T> in the way illustrated only if it is not abstract, but it is abstract. So how can I make it work in this case?
struct Base {
virtual void foo() = 0;
};
template <typename T>
struct CRTP : virtual Base {
CRTP (const Base& base) : Base(base) { }
CRTP() = default;
// virtual void foo() override { } // CRTP<T> is abstract.
};
struct Derived1 : CRTP<Derived1> {
Derived1 (const Base& base) : Base(base) { }
Derived1() = default;
virtual void foo() override { }
};
struct Derived2 : CRTP<Derived1> {
Derived2 (const Base& base) : Base(base) { }
Derived2() = default;
virtual void foo() override { }
};
template <typename T, typename U>
T* convert (const U& u) {
// return new T(u); // This works, but only if T(const Base&) constructor is defined in every Base concrete derived type.
return dynamic_cast<T*>(new CRTP<T>(u)); // This only works if CRTP<T> is not abstract.
}
int main() {
Derived1 d1;
Derived2* d = convert<Derived2, Derived1>(d1);
}
But, as a matter of fact, it is not a copy constructer, so it could be simply delegated like this:
struct Derived1 : CRTP<Derived1> {
using CRTP<Derived1>::CRTP;
Derived1() = default;
virtual void foo() override {
}
};
You can also use a pointer instead of a reference, which seems more relevant in your code by the way, because convert() returns a pointer. Such constructor is not considered as a copy constructor and can always be delegated to the children.

Forced to call the base constructor when using virtual inheritance although it will never be called?

I have a class Base which has a parameterized constructor and two classes Middle1 and Middle2 which virtually inherit from Base (in order to solve the diamond problem). In addition, class Foo inherits from Middle1 and Middle2.
Foo now calls the Base constructor explicitly and passes the parameter.
class Base
{
private:
int value;
protected:
Base(int& value) { this->value = value; }
};
class Middle1 : virtual public Base
{
protected:
Middle1() { }
};
class Middle2 : virtual public Base
{
protected:
Middle2() { }
};
class Foo : public Middle1, public Middle2
{
public:
Foo(int& value) : Base(value) { }
};
However, the code does not compile because Base lacks a default constructor and thus Middle1 and Middle2 don't have a default constructor to call, but need one which can be called by Foo.
Of course, I could now change the constructors of Middle1 and Middle2 to call the constructor of Base, too:
Middle1(int& value) : Base(value) { }
//...
Middle2(int& value) : Base(value) { }
// and then change my constructor of Foo:
Foo(int& value) : Base(value), Middle1(value), Middle2(value) { }
However, it seems rather clunky - especially given that because of the virtual inheritance, the Base constructor will never be called by Middle1 or Middle2 (they are not meant to be initialized, i.e. are basically abstract classes). Thus, having to introduce the parameter to the constructors of both Middle1 and Middle2 seems rather useless.
Is there any other way to make the above code compile without also having to introduce parameterized constructors in Middle1 and Middle2?
In virtual inheritance, the most-derived class has to directly call all of its ancestor constructors. Since Base doesn't have a default constructor, Middle1() and Middle2() can't compile if they can't pass an int& to Base().
However, in the code you have shown, there is no reason for Base() to take an int by reference. Pass it by value instead, and then Middle1() and Middle2() can pass 0 to Base():
class Base
{
private:
int value;
protected:
Base(int value = 0) { this->value = value; }
};
class Middle1 : virtual public Base
{
protected:
Middle1() { }
};
class Middle2 : virtual public Base
{
protected:
Middle2() { }
};
class Foo : public Middle1, public Middle2
{
public:
Foo(int value) : Base(value) { }
};
Though, I would suggest passing a pointer (or a std::optional) instead:
class Base
{
private:
int value;
protected:
Base(int* avalue = nullptr) { if (avalue) this->value = *avalue; }
};
class Middle1 : virtual public Base
{
protected:
Middle1() { }
};
class Middle2 : virtual public Base
{
protected:
Middle2() { }
};
class Foo : public Middle1, public Middle2
{
public:
Foo(int& value) : Base(&value) { }
};

C++: How to enforce derived class to set base member variables?

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.

c++ inheritance pointer

it's pretty diffecult for me to describe my problem.
I have two classes, I would say Base_A and Derived_A. You can see from the names, the class Derived_A is derived from Base_A. Also in my program I have other two classes Base_B and Derived_B (also with inheritance). The class Base_A contains the object of Base_B, and the class Derived_A contains the object of Derived_B.
class Base_A {
public:
Base_A() {}
virtual ~Base_A() {}
Base_B b_;
Base_B* pointer_;
void init() {
b_ = Base_B();
pointer_ = &b_;
pointer_->setValue(1);
}
void print() {
pointer_->getValue();
}
};
class Derived_A: public Base_A {
public:
Derived_A() {}
virtual ~Derived_A() {}
Derived_B b_;
Derived_B* pointer_;
void init() {
b_ = Derived_B();
pointer_ = &b_;
pointer_->setValue(2);
pointer_->increaseValue();
}
};
class Base_B {
public:
Base_B() {}
virtual ~Base_B() {}
int value_;
void setValue(int value) {
value_ = value;
}
void getValue() {
cout << "Base_B: " << value_ << endl;
}
};
class Derived_B: public Base_B {
public:
Derived_B() {}
virtual ~Derived_B() {}
void increaseValue() {
value_++;
}
};
int main() {
Derived_A derived_A = Derived_A();
derived_A.init();
derived_A.print();
return 0;
}
How you can see every class of A has one object of class B and pointer to this object. My problem is, when I call the function print(), it does not take Derived_B* pointer_, but try to access Base_B* pointer_, which is not exist. How I can say in my program, that it should take the pointer according to the class? Or do I need to declarate the Base_B* pointer_ inside the Derived_A class like:
Base::pointer_ = pointer_;
Maybe is there other method or algorithm for my problem?
Thank you a lot.
"but try to access Base_B* pointer_, which is not exist"
If DerivedA does not properly initialise BaseA, then DerivedA does not meet the "isA" rule for inheritance and the design needs changed. On the face of things:
Don't re-use names in the derived class such as b_, pointer_.
Its just confusing and you gain no value.
Make init() virtual.
Have DerivedA::init() call BaseA::init() explicitly.
Make pointer_ a virtual method.
Note the use of "covariant return types" for the virtual methods.
class BaseA
{
public:
virtual BaseB* pointer() { return &b_; }
// etc.
};
class DerivedA : public BaseA
{
public:
virtual DerivedB* pointer() { return &b_; }
// etc.
};
wouldn't Base_A have a pointer to Base_B if Base_A::init() was ever called?
why wouldn't you init the base class?

Initializing an abstract class?

Here is my issue. I want to have something like this:
class A {
protected:
int someInt;
virtual void someFunc() = 0;
};
class B : public A {
protected:
virtual void someFunc() { // uses someInt}
public:
B() {//tell the A inside of B to set someInt to whatever it wants}
};
so basically, someInt can be changed, it's not constant, but I want all the classes that implement A to use a value provided by A for someInt.
Thanks
You can use initializer lists in the constructor to call parent constructors:
class A {
protected:
int someInt;
virtual void someFunc() = 0;
A(int x) : someInt(x) {} // Base-class constructor (initialises someInt)
};
class B : public A {
protected:
virtual void someFunc() {}
public:
B() : A(10) {} // Initialises base class via constructor
};
Is this what you want?
class A
{
protected:
int someInt;
public:
A(int _val) : someInt(_val)
{
}; // eo ctor
}; // eo class A
class B : public A
{
public:
B() : A(5) // initialise someInt with 5
{
}; // eo ctor
}; // eo class B
Note, that as "someInt" is protected, you can just set it in B's constructor anyway.
B()
{
A::someInt = 5;
}; // eo ctor
I am not sure what you want, but if you initialize someInt in the constructor of A, subclasses will see that value.
class A {
public:
A() : someInt(5) {}
protected:
int someInt;
virtual void someFunc() = 0;
};
class B : public A {
protected:
virtual void someFunc() { // uses someInt}
public:
B() {// at this point someInt will already have been initialized to 5}
};
When the subclass is constructed, the baseclass constructors are executed first.
class A {
protected:
int someInt;
virtual void someFunc() = 0;
A(){//set someInt here}
};
class B : public A {
protected:
virtual void someFunc() { // uses someInt}
public:
B():A() {}
};
A protected constructor will achieve this. As above. The solutions using a public constructor are fine too, but as the constructor cannot be called directly on thr interface I think protected is better.