unique pointer of base class with derived member - c++

For my C++ program I have a lot of classes where a member should be of one of two types which have the same base class.
I thought I could implement this with pointers but I don't get it to work.
Example: lets assume we have a class A with a member b_ of class B:
class A{
public:
A(B b): b_{b} {}
private:
B b_;
}
The class B has only one function which is pure virtual:
class B{
public:
virtual void print() = 0;
}
now I have two derived classes of B and I want to change A in a way, that it could hold eihther objects of class B1 or B2:
class B1: public B{
public:
void print(){cout << "B1\n";}
}
class B2: public B{
public:
void print(){cout << "B2\n";}
}
My plan was to use unique pointers:
class A{
public:
A(std::unique_ptr<B> b): b_{std::move(b)} {}
private:
std::unique_ptr<B> b_;
}
int main(){
std::unique_ptr<B> b;
if (some condition){
b = make_unique<B1>(new B1()) ///?
}else{
b = make_unique<B2>(new B2()) ///?
}
A(b);
A.getB()->print();
}

There are several mistakes on your code. First of, you can't have two definitions of A. Second, you must pass the unique_ptr as r-value reference (std::move) since it is not copyable. Last, make a variable of type A (a) and then call methods on it.
#include <memory>
#include <iostream>
using namespace std;
class B{
public:
virtual void print() = 0;
virtual ~B() {};
};
class B1: public B{
public:
void print(){cout << "B1\n";}
};
class B2: public B{
public:
void print(){cout << "B2\n";}
};
class A{
public:
A(std::unique_ptr<B> b): b_{std::move(b)} {}
auto *getB() { return b_.get(); }
private:
std::unique_ptr<B> b_;
};
int main()
{
std::unique_ptr<B> b;
if(false)
b = make_unique<B1>();
else
b = make_unique<B2>();
A a(std::move(b));
a.getB()->print();
}

Related

c++ - Is it possible to declare a copy constructor in a derived class that references another derived class?

For example, if I create a Base class and 2 derived classes, DerivedOne and DerivedTwo, is it possible to declare a copy constructor in DerivedOne that references DerivedTwo?
Thanks
Are you looking for something like this?
#include <iostream>
using namespace std;
class B{
protected:
int a;
public:
B(int i):a(i){}
B(const B &b): a(b.a){cout<<"copying... ";} //base class copy constructor
virtual void print()=0;
};
class D1: public B{
//other functions and variables
public:
D1(): B(5){ /*other initializations*/ };
void print(){cout<<"D1:"<<a<<endl;}
};
class D2: public B{
//other functions and variables
public:
D2(const B &b):B(b){ /*other initializations*/ } //COPY CONSTRUCTOR
void print(){cout<<"D2:"<<a<<endl;}
};
int main() {
D1 d1;
d1.print(); // output: D1:5
B &b=d1;
D2 d2(b);
d2.print(); // output: copying... D2:5
return 0;
}
Tell me in comment if something is not clear.

runtime-check whether an instance (Base*) override a parent function (Base::f())

How to determine whether a pointer of base (B) class is (polymorphism-ly) override a certain virtual function of the base class?
class B{
public: int aField=0;
virtual void f(){};
};
class C : public B{
public: virtual void f(){aField=5;};
};
class D: public B{};
int main() {
B b;
C c;
D d;
std::vector<B*> bs;
bs.push_back(&b);
bs.push_back(&c);
bs.push_back(&d);
for(int n=0;n<3;n++){
//std::cout<<(bs[n]->f)==B::f<<std::endl;
//should print "true false true"
}
}
I tried to compare the address of function pointer bs[n]->f against B::f, but it is uncompilable.
Demo
I feel that this question might be duplicated, but I can't find (sorry).
GCC has an extension that allows you to get the address of a virtual member function.
This can be used like so:
#include <vector>
#include <iostream>
class B{
public: int aField=0;
virtual void f(){};
};
class C : public B{
public: virtual void f(){aField=5;};
};
class D: public B{};
int main() {
B b;
C c;
D d;
std::vector<B*> bs;
bs.push_back(&b);
bs.push_back(&c);
bs.push_back(&d);
for(int n=0;n<3;n++){
// This might need to be: (void*) B{}.*&B::f == (void*) (...)
std::cout << ((void*) &B::f == (void*)(bs[n]->*&B::f)) << '\n';
}
}
Demo
You may find this QA to be interesting.
Naturally, this is nonstandard behavior. If you wanted similar behavior in standard C++, you might actually be looking for pure virtual functions:
class B{
public: int aField=0;
virtual void f() = 0;
};
Otherwise, you'd have to have some other mechanism to communicate, such as a bool return type on f().

making base class functions invisible to client

I want to make all functions in my base class invisible to my client, only accessible through my derived class.
Is there a way to do this in C++?
Thanks!
There are two ways one is
Using Protected Keyword
class A{
protected:
void f(){
std::cout << "F" << std::endl;s
}
};
class B:public A{
// access f() here...
};
Any derived class can access f() function from A class.
Second way:
Making B class friend class of A.
#include <iostream>
class A{
private:
void f(){
std::cout << "F" << std::endl;
}
friend class B;
};
class B:public A{
A obj;
public:
void accessF(){
obj.f();
}
};
int main(){
B obj;
obj.accessF();
return 0;
}
Use access-specifier (if base class is not under your control):
class A
{ public:
void f() {}
void h() {}
};
class B: private A // all members of A are private
{ public:
void g()
{ f();
}
using A::h; // adjust access
};
int main()
{ A a;
a.f();
B b;
b.g();
b.h();
b.f(); // error: 'void A::f()' is inaccessible
}

Accessing the variable of the base class from derived class in Hybrid Inheritance

I have written a C++ program.
#include <iostream>
#include <string>
using namespace std;
class A
{
int a;
public:
void read()
{
cin>>a;
}
};
class B:public A
{
public:
B()
{ }
};
class C:public A
{
public:
C()
{}
};
class D:public B,public C
{
public:
void display()
{
cout<<a<<endl;
}
};
void main()
{
A a1;B b1;C c1;
D d1;
d1.display();
}
I get a message saying there is ambiguity. B is inheriting A.. So B class would inherit item 'a' from class A. Also, C class will inherit item 'a' from class A. Now if im trying to inherit both B and C classes in class D, which item 'a' will i be able to access ?? from class B or from class C ?? Is there any way where i can remove the ambiguity .?
You can fix your ambiguity problem by using one of the following options:
Be explicit about the base class
Use B as the explicit base class
void display()
{
cout<< B::a <<endl;
}
or use C as the explicit base class.
void display()
{
cout<< C::a <<endl;
}
Use virtual inheritance
Change B and C to use virtual inheritance.
class B: virtual public A
{
public:
B() {}
};
class C: virtual public A
{
public:
C() {}
};

Will the template argument's destructor to a templated class be called on deletion?

If you have a templated base class as in the following example:
class A{
public:
A();
virtual ~A();
};
template <class T>
class B : public T
{
public:
B();
virtual ~B();
};
typedef B<A> C;
class D : public C
{
public:
D();
virtual ~D();
};
When you delete an instance of D, will the destructor of A be called?
I'll probably create a test program to find out what happens, but just thinking about it, I wasn't sure what should happen.
When you delete an instance of D, will
the destructor of A be called?
Yes. Nothing special here (except you have private access on everything, which means it probably won't compile).
In a bid to get rep from two contradictory answers, given:
#include <iostream>
using namespace std;
class A{
public:
A() {}
virtual ~A() { cout << "~A()\n"; }
};
template <class T>
class B : public T
{
public:
B() {}
virtual ~B() {}
};
typedef B<A> C;
class D : public C
{
public:
D() {}
virtual ~D() {}
};
int main() {
D d;
}
Then yes, of course A's destructor will be called.