How can I omit a class inheritance? - c++

I'm trying to find my way around. I have two classes, A and B, where B inherits from A.
There are also two overloaded functions for A and B, that act on them in two different ways.
Now call these functions from a class function like this:
#include <iostream>
struct A;
struct B;
void f(A a);
void f(B b);
struct A {
int i;
A(): i(0) {};
void thisf() { f(*this); }
};
struct B: public A {
int j;
B(): j(1) {};
void thisf() { f(*this); }
};
void f(A a) { std::cout << a.i << std::endl; }
void f(B b) { std::cout << b.i << " " << b.j << std::endl; }
int main() {
A a;
B b;
a.thisf();
b.thisf();
return 0;
}
My question is: since A::thisf() and B::thisf() are the same (and will stay the same for more subclasses), is there a way how I can omit B::thisf() while still having the same functionality?
The expected output should look like:
0
0 1
More detail why I try to do this: I want to provide some custom render functionality to different kinds of data without bloating the class with render logic and have a separate render class with some state variables. But I don't want to give up the possibility to write
b.render()
in some situations. In my class definitions I want to spare every line I can.
I got the idea in this thread: https://gamedev.stackexchange.com/questions/63912/visitor-pattern-vs-inheritance-for-rendering

In your proposed problem you claim the need for a method in A and B that is not polymorphic and yet exhibits different behaviour in the two classes (linked by inheritance) with the same signature.
In addition, the method defers to a free function found by ADL (good!).
So... my question to you is this. If you already have the guarantee of a free function called f(A|B), why not simply document that as the interface?
If you insist on having thisf() you are causing yourself a problem because the inheritance relationship will cause B's thisf() to be ambiguous with A's. This can be solved with polymorphism (as per the other answer) but since you're rejecting that, you are are left with few options other than to eliminate the logically redundant thisf() altogether.
in any case, this code will do exactly as you want:
#include <iostream>
struct A;
struct B;
void f(A a);
void f(B b);
struct common_interface {
virtual void thisf() = 0;
};
template<class Host, class Base>
struct common_interface_impl : Base {
virtual void thisf() {
f(static_cast<Host&>(*this));
}
};
struct A : common_interface_impl<A, common_interface>
{
int i;
A(): i(0) {};
};
struct B: common_interface_impl <B, A>
{
int j;
B(): j(1) {};
};
void f(A a) { std::cout << a.i << std::endl; }
void f(B b) { std::cout << b.i << " " << b.j << std::endl; }
int main() {
A a;
B b;
a.thisf();
b.thisf();
return 0;
}

#include <iostream>
struct A {
int i;
A(): i(0) {};
virtual ~A() {};
virtual void thisf() { std::cout << i << std::endl; }
};
struct B: public A {
int j;
B(): j(1) {};
void thisf() { A::thisf(); std::cout << j << std::endl; }
};
void f( A* a )
{
a->thisf();
}
int main() {
A* a = new A();
A* b = new B();
f( a ); f( b );
delete a; delete b;
return 0;
}

Related

Call derived class methods from CRTP base class object

Is there a way that we can call derived class's method from base class object for which base doesn't provide an interface to call? I would like to do something like this
template<typename T>
struct A
{
using Derived = T;
void print()
{
static_cast<T*>(this)->print_();
}
void print_()
{
std::cout << "Base" << std::endl;
}
void a()
{
std::cout << "Aa" << std::endl;
}
};
struct B : public A<B>
{
void print_()
{
std::cout << "BD" << std::endl;
}
void b()
{
std::cout << "Bb" << std::endl;
}
};
struct C : public A<C>{
void c()
{
std::cout << "Cc" << std::endl;
}
};
int main()
{
A<B> b;
A<C> c;
b.print();
c.print();
B bd;
b.a();
bd.b(); // This works
// b.b(); // I understand this doesn't work, but I want to make this work.
C bc;
c.a();
bc.c(); // Same as class A<C> and C
}
I can provide interfaces to call those functions but I would like to know if this is achievable in the first place. Any solutions or comments on feasibility is much appreciated.
PS: I am just curious about this, as I got an unintentional error when I incorrectly instantiated the class.
Is there a way that we can call derived class's method from base class object for which base doesn't provide an interface to call?
Yes, as Jarod42 suggested, you can implement operator-> in A. You can't overload operator. so you'll have to use -> when calling such methods.
template<typename T>
struct A {
T* operator->() { return static_cast<T*>(this); }
};
You will now be able to compile this:
A<B> b;
b->print_();
b->b();
But: Your program will have undefined behavior. b is not a B. It's an A<B> that doesn't inherit from B so you will call non-static member functions on a non-existing object.
I suggest that you prevent instantiating A:s that doesn't have the proper CRTP relationship.
template<typename T>
struct A {
T* operator->() { return static_cast<T*>(this); }
private:
A() = default; // hidden from all ...
friend T; // ... except T
};
You can now instantiate B, but not A<B> or C if someone makes a bogus inheritance like this:
struct X {};
struct C : A<X> {}; // C can't be instantiated. A is friend of X, not C
Demo
Simple case: If you add a static function there is a safe way (because it would not access instance date).
Complicated case: the b.b(): This almost works but it's definitely a bad idea. As long as function does not refer to any instance variable it would be relatively safe. But otherwise it will definitely crash. The reason is b does not have B instance.
template<typename T>
struct A
{
typedef typename T Derived;
typedef typename A<T> AT;
void print()
{
static_cast<T*>(this)->print_();
}
void print_()
{
std::cout << "Base" << std::endl;
}
void a()
{
std::cout << "Aa" << std::endl;
}
//these conversion operators are for b.b() case. very bad idea!
operator Derived* () {
return static_cast<T*>(this);
}
operator Derived& () {
return static_cast<Derived&>(*this);
}
};
struct B : public A<B>
{
void print_()
{
std::cout << "BD" << std::endl;
}
static void static_b()
{
std::cout << "Bb::static_b" << std::endl;
}
void b()
{
std::cout << "Bb::b" << std::endl;
}
};
void test()
{
b.A<B>::Derived::static_b(); // This should work.
b.AT::Derived::static_b(); // This works with "AT" but it's recursive template. Not good.
((B&)b).b(); //This works but even though operator is implicit, it cannot implicitly know what to do. Nor will "auto".
//This works but even though operator is implicit, it cannot implicitly know what to do. Nor will "auto".
B& br = b;
br.b();
}

How to initialize member variables before inherited classes

I'm trying to make one class which requires member variables to be initialized first. I know why this happens, but is there a way around this?
Current print order:
second
first
Wanted print order:
first
second
#include <iostream>
struct A {
A() {
std::cout << "first" << '\n';
}
};
struct B {
B() {
std::cout << "second" << '\n';
}
};
struct C : public B {
C() : a(), B() {
}
A a;
};
int main() {
C c;
return 0;
}
Stick your members that need initializing first in a struct and inherit privately from that, before B.
struct A {
A() { std::cout << "first" << '\n'; }
};
struct B {
B() { std::cout << "second" << '\n'; }
};
struct Members { A a; };
struct C : private Members, public B {
C() : Members(), B() {}
};
int main() {
C c;
}
The downside with this is that there is no way to avoid exposing the "member struct" to the outside world, but that shouldn't be a problem in practice.
In C++ base classes will be initialized before any member variables of a derived class.
The best recourse given the information you've provided is to prefer composition over inheritance:
struct A {
A() {
std::cout << "first" << '\n';
}
};
struct B {
B() {
std::cout << "second" << '\n';
}
};
struct C {
A a;
B b;
};
This will exhibit the desired behavior
Make A a needed reference for C:
#include <iostream>
struct A {
A() {
std::cout << "first" << '\n';
}
};
struct B {
B() {
std::cout << "second" << '\n';
}
};
struct C : public B {
C(const A& a) : _A(a), B() {}
const A& _A;
};
int main() {
A a;
C c(a);
return 0;
}

Namehiding and overriding - Is there a way to make a function explicitly not overriding

I would like to hide a virtual method instead of override. I know for historic / compatibility reasons the override specifier is optional and overriding happens implicitly.
To stop overriding I usually adjusted the signature by adding a defaulted "Dummy" parameter. Is there a better way?
Assume this code:
#include <iostream>
class A{
public:
virtual void Foo()
{
std::cout << "A::Foo";
}
};
class B : public A
{
public:
void Foo() /*not override, just hide*/
{
std::cout << "B::Foo";
}
};
int main()
{
B b{};
A& a = b;
a.Foo(); //should print A::Foo - but prints B::Foo
}
What I did so far is this:
#include <iostream>
class A{
public:
virtual void Foo()
{
std::cout << "A::Foo";
}
};
template<typename T>
class reintroduce{};
class B : public A
{
public:
void Foo(reintroduce<B> = {}) /*not override, just hide*/
{
std::cout << "B::Foo";
}
};
int main()
{
B b{};
A& a = b;
a.Foo(); //should print A::Foo
}
The question is not too clear on the requirements of "hiding" but the following effectively "hides" the inherited method in the derived class, while not changing its visibility/accessibility in the base class.
#include <iostream>
class A {
public:
virtual void Foo()
{ std::cout << "A::Foo"; }
};
class B : public A
{
private:
using A::Foo;
};
int main()
{
B b;
b.Foo(); // error, cannot access private member
b.A::Foo(); // ok, calls A::Foo
A& a = b;
a.Foo(); // ok, calls A::Foo
}

Size of derived class in virtual base class function

Consider the following code
class A {
int x, y;
public:
A(){}
virtual void PrintSize(){ cout << sizeof(typeof(*this)) << endl; }
};
class B : public A {
int a, b, c;
public:
B(){}
};
int main() {
A obja;
B objb;
obja.PrintSize();
objb.PrintSize();
}
The intent of "PrintSize()" is to get the size of the current class where we are calling it from. What happens is that this-keyword refers to class A even though we are calling it from B. We don't want this since we need this function to be general for child classes.
We could obviously redefine the function verbatim to every class. The code would become harder to hande since there's so many unnesessary lines. Not to mention that re-writing the function to every class would defeat the purpose of deriving it in the first place.
Here's my temporary fix:
class A {
public:
virtual void PrintSize(){ cout << sizeof(typeof(*this)) << endl; }
};
class B : public A {
public:
virtual void PrintSize(){ cout << sizeof(typeof(*this)) << endl; }
};
class C : public A {
public:
virtual void PrintSize(){ cout << sizeof(typeof(*this)) << endl; }
};
class D : public A {
public:
virtual void PrintSize(){ cout << sizeof(typeof(*this)) << endl; }
};
While the accepted answer may have solved the immediate problem, you suddenly have no common base class for B and C. They inherit from two unrelated classes, namely A<B> and A<C>.
An alternative is to create a common base that defines an interface (called Interface below) and to add the CRTP class template between the derived classes and the interface. This lets you keep pointers and references to Interface and call the virtual member functions using those.
Here's an example of storing pointers to the common base class in a vector:
#include <iostream>
#include <memory>
#include <vector>
struct Interface {
virtual ~Interface() = default;
virtual void PrintSize() const = 0;
virtual void do_stuff() const = 0;
};
template<typename T>
struct Printer : public Interface {
void PrintSize() const override {
std::cout << sizeof(T) << '\n';
}
};
class B : public Printer<B> {
int a{};
public:
void do_stuff() const override { std::cout << "B doing stuff\n"; }
};
class C : public Printer<C> {
int a{}, b{}, c{};
public:
void do_stuff() const override { std::cout << "C doing stuff\n"; }
};
int main() {
std::vector<std::unique_ptr<Interface>> objs;
objs.emplace_back(std::make_unique<B>());
objs.emplace_back(std::make_unique<C>());
for(auto& ptr : objs) {
ptr->do_stuff();
ptr->PrintSize();
}
}
Possible output:
B doing stuff
16
C doing stuff
24
You can use the CRTP idiom to do this.
https://eli.thegreenplace.net/2011/05/17/the-curiously-recurring-template-pattern-in-c
The idea is the parent class is a template, so you can have access to the type of the child class directly in it.
With that, you'll be able to remove all "PrintSize" from child class.
Example :
template <typename Derived>
class A {
int x, y;
public:
A() {}
void PrintSize() { cout << sizeof(Derived) << endl; }
};
class B : public A<B> {
int a, b, c;
public:
B() {}
};
class C : public A<C> {
public:
C() {}
};
int main() {
C objc;
B objb;
objc.PrintSize();
objb.PrintSize();
}
The output is :
8
20

Method nonvisibility in base class despite definition in derived class; polymorphism and using `virtual` keyword

#include <iostream>
class A {
protected:
int foo;
};
class B : public A {
public:
B(int bar) { foo = bar; }
int method() { return foo; }
};
class C {
private:
A baz;
public:
C(A faz) { baz = faz; }
A get() { return baz; }
};
int main(void) {
C boo(B(1));
std::cout << boo.get().method() << std::endl;
return 0;
}
I have a base class A which B is a derived class of. Class C takes an A yet I have passed a derived class (B) in its place. No warnings or errors passing a B to C, but I'd like to have method visibility of method() in the above situation.
I'm not very familiar with virtual but I did try to add virtual int method() = 0; to A which lead to further errors.
Consider were I to add a second derived class:
class D : public A {
public:
D(int bar) { foo = bar; }
int method() { return foo+1; }
};
I'd like C to be able to take either B or D and my best assumption would be to take an A and let it handle it.
How do I use polymorphism correctly in this fashion?
Expected output with the below:
int main(void) {
C boo(B(1));
C boz(D(2));
std::cout << boo.get().method() << std::endl;
std::cout << boz.get().method() << std::endl;
return 0;
}
Would be:
1
3
First of all, in order to use A polymorphically, you need to add a virtual destructor, otherwise you will run into undefined behavior when trying to destroy the object. Then the method that you want to call through A must be virtual as well. If it shouldn't have an implementation in the base class itself, make it pure virtual:
class A {
protected:
int foo;
public:
virtual ~A() {}
virtual int method() = 0;
};
Then in C you need to use pointers or references to A, since polymorphism only works with those.
If you want C to own the A, as your code example to suggest, then you need to provide a destructor deleting the pointer and you need to disable copying of the class (or decide on some useful semantics for it):
class C {
private:
C(const C&); // Don't allow copying
C& operator=(const C&); // Don't allow copying
A* baz;
public:
C(A* faz) : baz(faz) { }
~C() { delete baz; }
A& get() { return *baz; }
};
int main(void) {
C boo(new B(1));
C boz(new D(2));
std::cout << boo.get().method() << std::endl;
std::cout << boz.get().method() << std::endl;
return 0;
}
Ideally you would upgrade to C++11 and use std::unique_ptr<A> instead of A* as member. But even if you can't do that, consider using boost::scoped_ptr<A>, which will manage the deletion for you (you don't need the destructor) and will make the class non-copyable by default. It also provides better exception-safety to encapsulate allocations in smart pointers like that.
If you need to call method() of type B using base class type A there has to be lookup during the runtime. The lookup is necessary to answer the question: Which method should be called? - the one that corresponds the type in a current line? Or other method in inheritance hierarchy?" If you expect method() from class B to be called when you have pointer or reference to A then you have to create a lookup table. This table is called vtable (from virtual functions table) and it's defined by adding virtual keyword to functions.
#include <iostream>
class A {
public:
virtual ~A(){}
virtual int method() = 0;
protected:
int foo;
};
class B : public A {
public:
B(int bar) { foo = bar; }
int method() {
std::cout << "Calling method() from B" << std::endl;
return foo; }
};
class C {
private:
A* baz;
public:
C(A* faz) { baz = faz; }
A* get() { return baz; }
};
int main(void) {
A* element = new B(1);
C boo(element);
boo.get()->method();
return 0;
}
It prints "Calling method() from B". Please keep in mind that the code is for presentation purposes and it's not good from best practices perspective.