How to do multiple inheritance just for function?
must share data of the base class
no virtual function (assume that vtable is expensive)
avoid virtual inheritance
implementation must be able to reside in .cpp
c++14 is allowed
Here are similar questions :-
Multiple inheritance in diamond shape with functions only - use virtual inheritance. Virtual inheritance is generally bad and expensive.
multiple inheritance without virtual inheritance - focuses on syntax and compiling rather than programming technique.
Multilevel inheritance in c++ (CRTP) , CRTP and multilevel inheritance , Eliminate redundancy with CRTP and multiple inheritance (C++03) and Using CRTP with virtual inheritance - implementation must be in header
Here is a sample code (coliru demo) :-
class O{
protected: int database=0;
};
class A : public O{
public: void print(){
std::cout<<database<<std::endl;
}
};
class B : public O{
public: void set(int s){
database=s+1;
}
};
class AB : public O{
public: void print(){//duplicate
std::cout<<database<<std::endl;
}
public: void set(int s){//duplicate
database=s+1;
}
};
//AB ab; ab.set(1); ab.print(); // would print 2
Here is my attempt (wandbox demo). I abuse CRTP :( :-
class O{
public: int database=0;
};
template<class T>class OA{
public: void print(){
std::cout<<static_cast<T*>(this)->database<<std::endl;
}
};
template<class T>class OB{
public: void set(int s){
static_cast<T*>(this)->database=s+1;
}
};
class A :public O,public OA<A>{};
class B :public O,public OB<B>{};
class AB :public O,public OA<AB>,public OB<AB>{};
It works, but it looks inelegant.
Furthermore, implementation must be in header (because OA and OB are template classes).
Are there better approaches? Or is this the way to go?
Sorry if it is too newbie question or already asked. I am a C++ beginner.
Edit
Give extended example of using please.
In ECS, it would be useful in some cases :-
class O{
protected: EntityHandle e;
};
class ViewAsPhysic : public O{ //A
public: void setTransform(Transformation t){
Ptr<PhysicTransformComponent> g=e;
g->transform=t;
}
};
class ViewAsLight : public O{ //B
public: void setBrightness(int t){
Ptr<LightComponent> g=e;
g->clan=t;
}
};
class ViewAsLightBlock : public O{ //AB
//both functions
};
The problem here is that the database field is member of class O. So without virtual inheritance, A and B will have each their own copy of database. So you must find a way to force A and B to share same value. You could for example use a reference field initialized in a protected constructor:
#include <iostream>
class O{
int _db;
protected: int &database;
O(): database(_db) {};
O(int &db): database(db) {};
};
class A : public O{
public: void print(){
std::cout<<database<<std::endl;
}
A() {} // public default ctor
protected: A(int& db): O(db) {}; // protectect ctor
};
class B : public O{
public: void set(int s){
database=s+1;
}
B() {} // public default ctor
protected: B(int& db): O(db) {}; // protectect ctor
};
class AB : public A, public B {
int _db2;
public: AB(): A(_db2), B(_db2) {}; // initialize both references to same private var
};
int main() {
AB ab;
ab.set(1);
ab.print();
return 0;
}
displays as expected:
2
Above code uses no virtual inheritance, no virtual function and no templates, so method can safely implemented in cpp files. The class AB actually uses methods from its both parents and has still a coherent view on its underlying data. In fact it simulates an explicit virtual inheritance by building the common data in the most derived class and injecting in through protected constructors in its parents.
Something like this?
must share data of the base class - check
no virtual function (assume that vtable is expensive) - check
avoid virtual inheritance - check
implementation must be able to reside in .cpp- check
c++14 is allowed - check. c++11 used.
#include <iostream>
class O {
protected:
int database = 0;
};
/*
* the concept of implementing print for a base class
*/
template<class...Bases>
struct implements_print : Bases... {
void print() const {
std::cout << this->database << std::endl;
}
};
/*
* The concept of implementing set for a base class
*/
template<class...Bases>
struct implements_set : Bases... {
void set() {
++this->database;
}
};
struct B : implements_set<O> {
};
struct A : implements_print<O> {
};
struct AB : implements_set<implements_print<O>> {
};
int main() {
A a;
a.print();
B b;
b.set();
AB ab;
ab.set();
ab.print();
}
Another way, using composition and an access class to provide access to the protected member. This example shows how to defer the work on database to another compilation unit:
#include <iostream>
/*
* this stuff in cpp
*/
namespace implementation
{
void print(const int& database) {
std::cout << database << std::endl;
}
void set(int& database) {
++database;
}
}
/*
* this stuff in header
*/
struct OAccess;
class O {
private:
int database = 0;
friend OAccess;
};
struct OAccess {
template<class Host>
constexpr decltype(auto) database(Host &host) const { return (host.database); } // note: () makes reference
template<class Host>
constexpr decltype(auto) database(Host const &host) const { return (host.database); } // note: () makes reference
};
/*
* the concept of implementing print for a derived class
*/
template<class Host>
struct implements_print {
void print() const {
OAccess access;
implementation::print(access.database(self()));
}
private:
decltype(auto) self() const { return static_cast<Host const &>(*this); }
};
/*
* The concept of implementing set for a derived class
*/
template<class Host>
struct implements_set {
void set() {
OAccess access;
implementation::set(access.database(self()));
}
private:
decltype(auto) self() { return static_cast<Host &>(*this); }
};
template<template<class> class...Impls>
struct OImpl : Impls<OImpl<Impls...>> ..., O {
};
using B = OImpl<implements_set>;
using A = OImpl<implements_print>;
using AB = OImpl<implements_print, implements_set>;
int main() {
A a;
a.print();
B b;
b.set();
AB ab;
ab.set();
ab.print();
}
We start with defining the concepts of things that can print and things that can be set:
namespace util {
template<class Base, class Derived, class R=void>
using if_base = std::enable_if_t< std::is_base_of< std::decay_t<Base>, std::decay_t<Derived>>::value, R >;
struct stub {};
}
namespace concepts {
template<class Token>
void do_print(Token, util::stub const&)=delete;
template<class Token>
void do_set(Token, util::stub&, int)=delete;
struct has_print {
struct token { friend struct has_print; private: token(int){} };
template<class T>
friend util::if_base<has_print, T> print(T const& t) {
do_print(get_token(), t);
}
private: static token get_token() { return 0; }
};
struct has_set {
struct token { friend struct has_set; private: token(int){} };
template<class T>
friend util::if_base<has_set, T> set(T& t, int x) {
do_set(get_token(),t, x);
}
private: static token get_token() { return 0; }
};
}
We then declare O and the operations you can support on it:
namespace DB {
class O;
void do_print(::concepts::has_print::token, O const& o);
void do_set(::concepts::has_set::token, O& o, int);
class O{
protected: int database=0;
friend void do_print(::concepts::has_print::token, O const&);
friend void do_set(::concepts::has_set::token, O&, int);
};
class A : public O, public concepts::has_print {
};
class B : public O, public concepts::has_set {
};
class AB : public O, public concepts::has_print, concepts::has_set {
};
}
void DB::do_print(::concepts::has_print::token, O const& o ) { std::cout << o.database << std::endl; }
void DB::do_set(::concepts::has_set::token, O& o, int x) { o.database = x+1; }
The hard part of this is the access control.
I ensure it isn't possible to call do_set except through has_set::set.
That is what all those tokens are about. You can strip them out and their overhead if you are willing to just say "don't call the do_ functions" (and maybe give them another name, like private_impl_set).
Live example.
To start discussion.
class O
{
// no virtual destructor. So cant use polymorphic deletion
// like :
// O *o = new AB;
// delete o;
protected: int database=0;
};
class A : virtual public O{
public: void print(){
std::cout<<database<<std::endl;
}
};
class B : virtual public O{
public: void set(int s){
database=s+1;
}
};
class AB : protected A, protected B{}; // no vtable
void foo() {
AB ab;
ab.print(); // won't perform virtual call.
}
Related
I have several disparate templated pure abstract classes. I derive from these to get a bunch of classes, and from there, I can use those to make a bunch of objects. I would like to put all of these objects into a container. However, they are all of different types. I am wondering how to accomplish this late-stage polymorphism.
Say this is my pre-existing code that I have right now:
#include <iostream>
template<typename T>
class A{
public:
A() : m_num(1.0) {};
virtual ~A() {};
virtual void printNum() const = 0;
protected:
T m_num;
};
template<typename T>
class B{
public:
B() : m_num(2.0) {};
virtual ~B() {};
virtual void printTwiceNum() const = 0;
protected:
T m_num;
};
class A_example : public A<int>
{
public:
A_example() : A<int>() {};
void printNum() const { std::cout << m_num << "\n"; };
};
class B_example : public B<int>
{
public:
B_example() : B<int>() {};
void printTwiceNum() const { std::cout << 2*m_num << "\n"; };
};
int main(){
A_example first;
B_example second;
first.printNum();
second.printTwiceNum();
return 0;
}
With more classes, it could get pretty messy inside of main(). Ideally I could jut iterate over the container and call print() on each element. My first thought is to use a std::vector<unique_ptr<Base>>. This seems to work:
#include <iostream>
#include <vector> // new include
#include <memory> // new include
#include <utility> // new include
// new Base class here
class Base{
public:
virtual ~Base(){};
};
template<typename T>
class A : public Base{ // new inheritance here
public:
A() : m_num(1.0) {};
virtual ~A() {};
virtual void printNum() const = 0;
protected:
T m_num;
};
template<typename T>
class B : public Base{ // new inheritance here as well
public:
B() : m_num(2.0) {};
virtual ~B() {};
virtual void printTwiceNum() const = 0;
protected:
T m_num;
};
class A_example : public A<int>
{
public:
A_example() : A<int>() {};
void printNum() const { std::cout << m_num << "\n"; };
};
class B_example : public B<int>
{
public:
B_example() : B<int>() {};
void printTwiceNum() const { std::cout << 2*m_num << "\n"; };
};
int main(){
std::vector<std::unique_ptr<Base>> v;
v.emplace_back( new A_example() );
v.emplace_back( new B_example() );
//v[0]->printNum(); // nope
//v[1]->printTwiceNum(); // nope
return 0;
}
This is cool because I didn't have to change A_example or B_example, and all I changed in A and B was that I added : public Base. However, I have no idea how to call each elements print*** function. Is there any way to call the printNum() and printTwiceNum() functions, and for them to be automatically recognized?
The simplest approach is to just make a virtual function Base::print and have your derived classes implement it. But that's not always appropriate.
Another approach is to branch on dynamic_cast conversions. The premise there is that some functions are only available on some classes. But this can get hairy especially when using class templates, as you must handle all expected template parameters.
To generalize this, you can use interface classes. Let's say you have lots of different classes but only a small number of print variations. In that case, it may make sense to do this:
class PrintNumInterface {
public:
virtual void printNum() const = 0;
};
class PrintTwiceNumInterface {
public:
virtual void printTwiceNum() const = 0;
};
template<typename T> class A : public Base, public PrintNumInterface { ... };
template<typename T> class B : public Base, public PrintTwiceNumInterface { ... };
And now, no matter how many additional classes or template expansions you have to deal with, you only need to handle these interfaces:
for (auto& p : v)
{
if (PrintNumInterface* iface = dynamic_cast<PrintNumInterface*>(p.get())
iface->printNum();
else if (PrintTwiceNumInterface* iface = dynamic_cast<PrintTwiceNumInterface*>(p.get())
iface->printTwiceNum();
}
Say I've got the following (pseudo-)code:
class base{
public:
virtual void callMe() = 0;
virtual void doRender() = 0;
}
class a : public base{
public:
virtual void callMe(){/*doA*/} override;
}
class b : public base{
public:
virtual void callMe(){/*doB*/} override;
}
class myClass : public base, public a, public b{
public:
virtual void doRender(){
this->a::callMe();
this->b::callMe();
} override;
}
Would there be a way to write this differently? Something like:
class myClass : public base, public a, public b{
public:
virtual void doRender(){
this->allSupers::callMe();
} override;
}
My goal with this would be to have a base class that can be extended to have different "features", all of which have to be executed on doRender.
I know I could of course keep track of these functions by means of a function pointer list in base, in which the subclasses put their own functions when constructed, but I'd like to avoid that. Having to iterate over these functions still gives me at least three lines of code in my final doRender. (Or one long unreadable line.)
I'm open for suggestions using templates.
Depending on you actual problem at hand, you might be able to use the mixin-style. Essentially you can have each class call the next callMe at the end (or begining) of their own callMe. One benefit is that callMe does not need to be a virtual function. Here is a minimal example (online):
#include <iostream>
class base
{
public:
void callMe() {}; // Empty base case
virtual void doRender() = 0;
};
template <class super>
class a : public super
{
public:
void callMe()
{
std::cout << "doA" << '\n';
super::callMe(); // Call the next
};
};
template <class super>
class b : public super
{
public:
void callMe()
{
std::cout << "doB" << '\n';
super::callMe(); // Call the next
};
};
template <class super>
class myClass_t : public super
{
public:
void doRender()
{
super::callMe();
};
};
using myClass = myClass_t<a<b<base> > >; // Defining the order of evaluation;
int main()
{
myClass m;
m.doRender();
}
With variadic template, you may do:
template <typename ... Ts>
class myClassTs : public base, public Ts...
{
public:
virtual void doRender(){
int dummy[] = {0, (Ts::callMe(), void(), 0)...};
static_cast<void>(dummy); // Silent warning for unused variable
} override;
}
using myClass = myClassTs<a, b>;
And in C++17, it would be
template <typename ... Ts>
class myClassTs : public base, public Ts...
{
public:
virtual void doRender(){
(static_cast<void>(Ts::callMe()), ...);
} override;
}
I'm reading the book by Alexandrescu, and I've run into the Acyclic Visitor pattern. I think that it's possible to get rid of the macross that calls AcceptImpl method of the BaseVisitable class.
Could you tell me, whether the following implementation bellow conforms the standard?
class BaseVisitor
{
public:
virtual ~BaseVisitor() {}
};
template <class SpecificVisitable>
class SpecificVisitor
{
public:
virtual void Visit(SpecificVisitable& t) = 0;
protected:
~SpecificVisitor() {}
};
template <class SpecificVisitable>
class BaseVisitable
{
public:
void Accept(BaseVisitor& visitor)
{
SpecificVisitor<SpecificVisitable>& specificVisitor = dynamic_cast<SpecificVisitor<SpecificVisitable>&>(visitor);
specificVisitor.Visit(static_cast<SpecificVisitable&>(*this));
}
protected:
~BaseVisitable() {}
};
class A : public BaseVisitable<A>
{
public:
void PrintA() { std::cout << "A\n"; }
};
class B : public BaseVisitable<B>
{
public:
void PrintB() { std::cout << "B\n"; }
};
class PrintVisitor final:
public BaseVisitor,
public SpecificVisitor<A>,
public SpecificVisitor<B>
{
public:
virtual void Visit(A& a) override
{
a.PrintA();
}
virtual void Visit(B& b) override
{
b.PrintB();
}
};
int main()
{
A a;
B b;
PrintVisitor visitor;
a.Accept(visitor);
b.Accept(visitor);
}
I agree with the commenters to the original post that state that a dynamic_cast to a reference will fail. You are not testing that situation, so your code will of course work just fine. But, in the general case, it's wrong.
I recommend that you instead rewrite BaseVisitable to instead cast to a pointer and check that pointer before dispatching on it. Something like
if (auto sv = dynamic_cast<SpecificVisitor<SpecificVisitable>*>(visitor))
sv->visit(*this)
I want a class that can only be instantiated as a member of another class.
Id est:
class A
{
public:
A() :
member_()
{};
void letBSayHi() { member_.sayHi(); }
private:
B member_;
};
class B
{
public:
void sayHi() { printf("hola!"); }
};
thus:
A alpha; // valid
alpha.letBSayHi(); // # hola!
B beta; // invalid
beta.sayHi(); // impossible
The singleton pattern obviously wouldn't work, as I want one instance of class B for every instance of class A. But any instantiation of class B other than as a class A-member should be prohibited.
Make B a private nested class of A:
class A {
public:
void letBSayHi() { member_.sayHi(); }
private:
class B {
public:
void sayHi() { std::cout << "hola!"; }
};
B member_;
};
Addendum re: comment: The implementation can be separated from the declaration like this:
Header:
class A {
public:
void letBSayHi();
private:
class B {
public:
void sayHi();
};
B member_;
};
Source file:
void A::letBSayHi() { member_.sayHi(); }
void A::B::sayHi() { std::cout << "hola!\n"; }
// ^^^^-- interesting part here
Well, if you want to include, why not?
class A {
#include "B.hpp"
...
};
I have the following code :
class A{};
class B: public A{};
class C: public A{};
class MyVisitor
{
public:
void visit(B*);
void visit(C*);
};
And then collection of A* objects, I want to achieve the following :
1)
MyVisitor visitor;
for(vector<A*>::iterator it = vec.begin(); it!= vec.end();it++)
visitor->visit(a);
2) Somehow determine at compile time, if A* points to derived object D,and give compiler error, if MyVisitor::visit(D*) function is not present
I know that 1) is achievable with some multimethods implementation, I guess I can find some implementations of multimethods for c++ . But is 2) somehow possible ?
You could use dynamic_cast like this (inside the body of your for loop) since the behavior should vary at run-time (according to the actual type of data).
ClassB* ba = dynamic_cast<ClassB*>(a);
if (ba)
visitor->visit(ba);
ClassC* ca = dynamic_cast<ClassC*>(a);
if (ca)
visitor->visit(ca);
Maybe your visit functions might be declared virtual (for your ClassD thing).
Otherwise organize your classes as a tree (not a forest) of classes, and have your topmost root class
class Topmost {
virtual int classnum() const;
and adopt the convention that each non-abstract class gives its unique classnum etc... Or have a metaclass mechanism (like e.g. Qt has)
You can try something like this.
#include <iostream>
class A
{
virtual void visit() = 0;
};
class B: private A
{
public:
void visit()
{
std::cout << __PRETTY_FUNCTION__ << "\n";
}
};
class C: private A
{
public:
void visit()
{
std::cout << __PRETTY_FUNCTION__ << "\n";
}
};
template <typename... Args>
class MyVisitor : public Args...
{
public:
template <typename T>
void visit(T* t)
{
t->visit();
}
};
int main()
{
MyVisitor<B, C> visitor;
B b;
B* bp = &b;
visitor.visit(bp);
return 0;
}
Live example
You may apply the visitor pattern completly:
class B;
class C;
class IVisitor
{
public:
void visit(B&) = 0;
void visit(C&) = 0;
};
class A
{
virtual ~A() = default;
virtual void accept(IVisitor& v) = 0;
};
class B: public A{ void accept(IVisitor& v) override { v.visit(*this); } };
class C: public A{ void accept(IVisitor& v) override { v.visit(*this); } };