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?
Related
class Base
{
public:
virtual void f()
{
g();
}
virtual void g()
{
cout<<"base";
}
};
class Derived : public Base
{
public:
virtual void f()
{
Base::f();
}
virtual void g()
{
cout<<"derived";
}
};
int main()
{
Base *pBase = new Derived;
pBase->f();
return 0;
}
In this program I have kept both derived and base class functions as virtual. Is it possible call virtual functions of derived class through base class pointer and base class functions are not virtual.
Thanks in advance..
assuming functions in base class are not virtual
This can be achieved via type erasure. But there are caveats.
Your "base" class should decide between the two:
Being a view class (can't be called delete on or created by itself)
Being a resource owning class (implemented similar to 1, but stores a smart pointer).
Here is an example for case 1: https://godbolt.org/z/v5rTv3ac7
template <typename>
struct tag{};
class base
{
public:
base() = delete;
template <typename Derived>
explicit base(tag<Derived> t)
: _vTable(make_v_table(t))
{}
int foo() const { return _vTable.foo(*this); }
protected:
~base() = default;
private:
struct v_table
{
virtual int foo(const base &b) const = 0;
protected:
~v_table() = default;
};
template <typename Derived>
static const v_table& make_v_table(tag<Derived>){
struct : v_table
{
int foo(const base &b) const {
return static_cast<const Derived&>(b).foo();
}
} static const _vTable{};
return _vTable;
}
private:
const v_table& _vTable;
};
class derived : public base
{
public:
explicit derived()
: base(tag<derived>{})
{}
int foo() const { return 815; }
};
// example
#include <iostream>
int main(){
derived d{};
const base& b = d;
std::cout << b.foo() << '\n';
}
Take notice, that you can only take a pointer or a reference (cv-qualified) to a base class. The base class can't be created on its own.
Also tag<T> is needed to call a templated constructor.
DO NOT CALL DERIVED METHODS IN THE BASE CONSTRUCTOR OR DESTRUCTOR
Simple answer is no, if the function you are calling is not virtual. The Compiler would have no Idea that you are trying to call a function from the Derived Class, and won't make and I'm paraphrasing here since I do not know the proper term for,"Won't make proper entries in the Virtual Table".
class Base
{
public:
void f()
{
std::cout<<"Base f() Called\n";
g();
}
virtual void g()
{
std::cout<<"Base g()\n";
}
virtual ~Base(){std::cout<<"Base Destroyed\n";}
};
class Derived : public Base
{
public:
void f()
{
g();
}
virtual void g()
{
std::cout<<"Derived g()\n";
}
~Derived(){std::cout<<"Derived Destroyed\n";}
};
int main()
{
Derived* D1 = new Derived();
Base* B1 = D1;
B1->f();
delete B1;
return 0;
}
Have a look at the following code, I have not declared Base::f() as virtual,calling B1->f() calls the Base Method, but the base method calls a virtual function Base::g() and this allows the "Derived" method be called.
Have a look at this thread or this blogpost to understand Virtual Tables.
(1) and you must ALWAYS declare the destructor of a base class virtual when destroying Derived Object through a Base Pointer, else the resources used by the Derived Object will never get destroyed and it's memory will leak until the program closes.
Don't Take my word as gospel, I am simply passing on knowledge I have acquired from first hand experience, Except for (1), specially if you are not using smart pointers
If i have a base class Base:
class Base {
public:
bool foo;
virtual bool bar() = 0;
virtual ~Base() = default;
};
And two derived classes:
class Derived1 : public Base
{
Derived1();
bool bar() override;
}
class Derived2 : public Base
{
Derived2();
std::vector<baz*> bazVector;
bool bar() override;
}
And i have a vector std::vector<Base*> mainVector which us populated like this:
mainVector.push_back(someDerivedPointer)
At some point i need to determine what object is stored: Derived1 or Derived2, so i could access Derived2->bazVector if object is Derived2
One solution is trying to dynamic_cast<Derived2>(mainVector.at(someIndex)) and check for returned nullptr, or storing some enum that would tell me what class this object belongs to, but these solutions seem crutchy, and i wonder if there is a better solution.
As advised in the comment section, you are probably looking the wrong direction.
There's high chance you are not tackling the problem with the right approach.
If you need to write different logic based on the actual derived class from a pointer, you are missing something.
We don't have too much details, but for what you said, you have two options:
1: adding a virtual method to retrieve your vector:
class Base {
public:
bool foo;
virtual bool bar() = 0;
virtual ~Base() = default;
virtual std::vector<baz*> getVector() = 0;
};
class Derived1 : public Base
{
public:
Derived1();
bool bar() override;
virtual std::vector<baz*> getVector() override {return {};};
}
class Derived2 : public Base
{
std::vector<baz*> bazVector;
public:
Derived2();
bool bar() override;
virtual std::vector<baz*> getVector() override {return bazVector;};
}
2: insert the logic where you need this vector into a virtual function (this is probably the better):
class Base {
public:
bool foo;
virtual bool bar() = 0;
virtual ~Base() = default;
virtual void doSomething() = 0;
};
class Derived1 : public Base
{
public:
Derived1();
bool bar() override;
virtual void doSomething() override {/*no op*/};
}
class Derived2 : public Base
{
std::vector<baz*> bazVector;
public:
Derived2();
bool bar() override;
virtual void doSomething() override {/*do something with you bazVector*/};
}
The other answer is most likely the best way to go forward in OP's case, but considering how vague the question's title is, there is an alternative idiom that is sometimes useful when:
All the derived classes of Base are known ahead of time.
The derived classes are particularly heterogenous, and creating a lowest-common-denominator interface would be problematic in some way, shape, or form.
A good example of this would be an AST. clang's ASTConsumer uses a flavor of the technique.
The visitor. The basic idea is to have an external interface with virtual methods for each derived class, and have a single virtual function in Base that dispatches this to the correct function.
class Derived1;
class Derived2;
class Base {
public:
class Visitor {
public:
virtual void operator()(Derived1&) {}
virtual void operator()(Derived2&) {}
protected:
~Visitor() = default;
};
virtual void visit(Visitor& v) = 0;
virtual ~Base() = default;
};
class Derived1 : public Base
{
public:
Derived1(){}
void visit(Base::Visitor& v) override { v(*this); }
};
class Derived2 : public Base
{
public:
Derived2(){}
void visit(Base::Visitor& v) override { v(*this); }
};
// Usage example:
struct MyVisitor final : public Base::Visitor {
void operator()(Derived1& obj) override {
std::cout << "1\n";
}
void operator()(Derived2& obj) override {
std::cout << "2\n";
}
};
int main() {
std::vector<std::unique_ptr<Base>> bases;
bases.push_back(std::make_unique<Derived1>());
bases.push_back(std::make_unique<Derived2>());
MyVisitor v;
for(auto& b : bases) {
b->visit(v);
}
}
I have the following classes:
class Base {
public:
virtual ~Base(){}
Base() {}
virtual void foo() = 0;
};
class Derived : public Base {
public:
virtual ~Derived(){}
Derived() : Base() {}
void foo() { printf("derived : foo\n"); }
};
class IInterface {
public:
virtual ~IInterface() {}
virtual void bar() = 0;
};
class C : public Derived, public IInterface {
public:
virtual ~C(){}
C() : Derived(){}
void bar() { printf("C : bar\n"); }
};
now I have a bunch of Derived* objects and I want to apply different interfaces on them :
Derived* d = new Derived();
C* c = dynamic_cast<C*>(d);
c->bar();
c->foo();
dynamic_cast returns nullptr and with c-style cast i get seg fault.
is there anyway to achieve this?
note that my objects are already created with Derived ctor.
i just want to treat them differently using Interfaces
The only way to achive this is to create a new object and move the data over from the old object.
Try encapsulating the behaviour that needs to change at runtime. Instead of inheriting from the IInterface, you have a member variable that is an IInterface pointer. Then instead of overriding bar in the child class, you pass the call to bar through to whatever is being pointed at. This allows modular behavior that looks just like polymorphism, but is more flexible:
class IInterface {
public:
virtual ~IInterface() {}
virtual void bar() = 0;
};
class Derived : public Base {
public:
IInterface* m_bar;
virtual ~Derived(){}
Derived() : Base(){}
void bar() {return m_bar->bar(); }
void foo() { printf("derived : foo\n"); }
};
You then derive and create IInterface objects and can associate any of them with Derived objects.
Say I have an interface hierarchy :
class A
{
virtual void commonFunc() = 0;
};
class B1 : public A
{
virtual void b1SpecificFunc() = 0;
};
class B2 : public A
{
virtual void b2SpecificFunc() = 0;
};
Interface A only exist to avoid duplicating the commonFunc() function.
Now if I want to implement this in order to have 2 instanciatable classes ImplB1 and ImplB2 i could do :
class ImplA
{
virtual void commonFunc();
};
class ImplB1 : public ImplA
{
virtual void b1SpecificFunc();
};
class ImplB2 : public ImplA
{
virtual void b2SpecificFunc();
};
The problem with this is that it makes ImplA instanciatable, which I don't want to. I only want ImplB1 and ImplB2 to be instanciatable, because ImplA is something asbtract that only exist to have the implementation of the common function in common.
How could i design this please ? Thank you.
Interface A only exist to avoid duplicating the commonFunc() function.
You certainly mean to avoid duplicating its declaration, don't you?
class ImplA
{
virtual void commonFunc();
};
This should probably be:
class ImplA : public A
{
virtual void commonFunc();
};
And I guess the point is that ImplA actually has an implementation of commonFunc. So for the sake of this answer's brevity, let's put it into the class definition:
class ImplA : public A
{
virtual void commonFunc() {} // implementation
};
The problem with this is that it makes ImplA instanciatable.
Just make ImplA's destructor pure virtual:
class ImplA : public A
{
public:
virtual ~ImplA() = 0 {}
private:
virtual void commonFunc() {}
};
This will prevent instantiation even inside of derived classes' functions. For example, the following will create a compiler error:
class ImplB1 : public ImplA
{
public:
virtual void b1SpecificFunc()
{
ImplA a; // error, cannot instantiate abstract class
}
};
In fact, you will not even be able to instantiate the class in its own functions:
class ImplA : public A
{
public:
virtual ~ImplA() = 0 {}
private:
virtual void commonFunc()
{
ImplA a; // error, cannot instantiate abstract class
}
};
But seriously, this all seems pretty over-engineered. Perhaps what you really need is to make commonFunc a non-virtual protected function of A, which derived classes can then call if they need to.
Or perhaps commonFunc can just be a free-standing utility function?
You can do the following. Also, here is a SO question/answer about this.
Note: While I'm answering the question that you can do this I'm not asserting it's what you should do.
Code
#include <iostream>
class A
{
public:
virtual void commonFunc() = 0;
};
void A::commonFunc() // Pure virtual but implemented anyway
{
// Derived classes can explicitly opt-in to this implementation
std::cout << "A::commonFunc()\n";
}
class B1 : public A
{
public:
virtual void b1SpecificFunc() = 0;
};
class B2 : public A
{
virtual void b2SpecificFunc() = 0;
};
class ImplB1 : public B1
{
public:
// This function must be implemented because its declared pure virtual
virtual void commonFunc()
{
// Can override the behavior if desired...
A::commonFunc(); // Explicitly use default implementation
}
virtual void b1SpecificFunc()
{
std::cout << "b1SpecificFunc()\n";
}
};
class ImplB2 : public B2
{
public:
// This function must be implemented because its declared pure virtual
virtual void commonFunc()
{
// Can override the behavior if desired...
A::commonFunc(); // Explicitly use default implementation
}
virtual void b2SpecificFunc()
{
std::cout << "b2SpecificFunc()\n";
}
};
int main()
{
//A a; // Won't compile (as expected/desired)
ImplB1 b1;
ImplB2 b2;
b1.commonFunc();
b1.b1SpecificFunc();
b2.commonFunc();
b2.b2SpecificFunc();
return 0;
}
Output
A::commonFunc()
b1SpecificFunc()
A::commonFunc()
b2SpecificFunc()
I've posted about this problem before (Here), this is a different approach to a solution. This solution to be seems to better encapsulate the behavior for those implementing the class, since it prevents them from needing to explicitly up cast.
Here's the problem:
I have a project in which I want to isolate core behavior in most objects, while providing additional behavior through derived objects. Simple enough:
class BaseA
{
virtual void something() {}
}
class DerivedA : public BaseA
{
void something() {}
void somethingElse() {}
}
Now let’s say I also have a second set of classes, same inheritance scheme except that they aggregate the above classes. However, I would like the base version to use the base class, and the derived version in the derived class. My solution i was thinking about 'hiding' the base class variable by using the same name;
class BaseB
{
BaseA *var;
BaseB()
{
var = new BaseA();
}
virtual void anotherThing1();
virtual void anotherThing2();
virtual void anotherThing3();
}
class DerivedB : public BaseB
{
DerivedA *var;
DerivedB()
{
var = new DerivedA();
}
void anotherThing1();
void anotherThing2();
void anotherThing3();
void andAnother1();
void andAnother2();
}
The goal for this approach is so that functions that rely on the derived aggregated class no longer need to explicitly cast to achieve the gained functionality.
void func1( BaseB &b )
{
b.anotherThing1();
b.var->something();
}
void func2( DerivedB &b )
{
b.anotherThing1();
b.andAnother1();
b.var->something();
b.var->somethingElse();
}
void main( int argc, char **argv )
{
BaseB baseB;
DerivedB derivedB;
func1( baseB );
func1( derivedB );
func2( derivedB );
}
Would this be considered bad practice?
Would this be considered bad practice?
Yes, it would be bad practice, because the var in the Base would be unused. It does not look like DerivedB should be deriving from BaseB: instead, they should be derived from the same abstract base class, like this:
class AbstractB {
public:
virtual void anotherThing1() = 0;
virtual void anotherThing2() = 0;
virtual void anotherThing3() = 0;
};
class DerivedB1 : public AbstractB { // Former BaseB
BaseA *var;
public:
DerivedB1() {
var = new BaseA();
}
virtual void anotherThing1();
virtual void anotherThing2();
virtual void anotherThing3();
};
class DerivedB2 : public AbstractB { // Former DerivedB
DerivedA *var;
public:
DerivedB2() {
var = new DerivedA();
}
void anotherThing1();
void anotherThing2();
void anotherThing3();
void andAnother1();
void andAnother2();
};
General principle in use here is that you should try making all your non-leaf classes in your inheritance hierarchy abstract.