Consider the case of having two pure virtual classes, say X and Y. Y specifies a pure virtual method that returns a smart pointer to an instance of X (e.g. virtual unique_ptr<X> getX() const = 0). This is done so that subclasses of Y can return whatever implementation of X they desire.
However, this means that a user has to be aware that upon calling getX(), they should expect to work with an instance of unique_ptr<X> (not ideal). This is readily fixed by wrapping unique_ptr<X> in a class as in the following example:
#include <iostream> // cout, endl
#include <memory> // unique_ptr
using namespace std;
////////////////////////////////////////////////////////////////////////////////
struct X {
virtual void exampleMethod() = 0;
};
struct XCloneable : public X {
typedef unique_ptr<XCloneable> P;
virtual P clone() const = 0;
};
class XWrapper : public X {
XCloneable::P p;
public:
XWrapper(XCloneable::P p) noexcept : p(move(p)) {}
XWrapper(const XWrapper &that) noexcept : p(that.p->clone()) {}
XWrapper &operator=(const XWrapper &that) noexcept {
p = that.p->clone();
return *this;
}
XWrapper(XWrapper &&that) noexcept : p(move(that.p)) {
}
XWrapper &operator=(XWrapper &&that) noexcept {
p = move(that.p);
return *this;
}
virtual void exampleMethod() { p->exampleMethod(); }
};
////////////////////////////////////////////////////////////////////////////////
struct XX : public XCloneable {
virtual void exampleMethod() { cout << "XX" << endl; }
virtual XCloneable::P clone() const { return XCloneable::P(new XX); }
};
////////////////////////////////////////////////////////////////////////////////
struct Y {
virtual XWrapper getX() = 0;
};
struct YY {
virtual XWrapper getX() { return XWrapper(XCloneable::P(new XX)); }
};
////////////////////////////////////////////////////////////////////////////////
int main() {
YY yy;
auto x = yy.getX();
x.exampleMethod();
return 0;
}
However, this is quite verbose, and has to be written for each pure virtual class similar to X. I imagine it would not be too difficult to automatically generate wrappers such as the above systematically, although I would prefer to not run my code through anything other than the usual C preprocessor (although more exotic preprocessing solutions are welcome/interesting).
Is there a way to handle this scenario systematically?
The pattern you're talking about is an Abstract Factory. I'm really not sure why most of the code in your question exists though... Here is an example of an abstract factory implementation which should do what you need:
#include <iostream>
#include <memory>
class X
{
public:
virtual void exampleMethod() = 0;
};
class MyX : public X
{
public:
void exampleMethod() override
{
std::cout << "Calling MyX::exampleMethod()";
}
};
class XFactory
{
public:
virtual std::unique_ptr<X> createX() = 0;
static XFactory* getInstance()
{
return m_instance.get();
}
static void setInstance(std::unique_ptr<XFactory> instance)
{
m_instance = move(instance);
}
private:
static std::unique_ptr<XFactory> m_instance;
};
std::unique_ptr<XFactory> XFactory::m_instance = std::unique_ptr<XFactory>();
class MyXFactory : public XFactory
{
public:
std::unique_ptr<X> createX() override
{
return std::unique_ptr<X>(new MyX);
}
};
int main()
{
// Call setInstance with different XFactory implementations to get back
// different implementations of X.
std::unique_ptr<XFactory> xFactory(new MyXFactory);
XFactory::setInstance(move(xFactory));
std::unique_ptr<X> x = XFactory::getInstance()->createX();
x->exampleMethod();
return 0;
}
This example outputs:
Calling MyX::exampleMethod()
I don't see that you need a wrapper at all although there is no reason you couldn't return one from MyXFactory::createX() as long as it extends X.
EDIT:
I just re-read your question, why is it not ideal for the caller to know they are dealing with a unique_ptr? I would think that it is the most ideal. By giving them a unique_ptr you are explicitly saying to them: you own this now.
Related
I'm trying to allow a class to implement an interface, where the interface is templated to either allow an update internally or not. The code looks like this and works if the implementation is within the class declaration. If it is moved out (as shown here), I get a compiler error on Visual Studio 2019, and I can't understand why. All help is appreciated!
The following code will not compile. If the out of class implementation and headers are modified to just use the code I commented out, it compiles and works as expected.
#include <atomic>
#include <cstdint>
#include <memory>
#include <iostream>
#include <string>
enum class EntryType { Read, ReadUpdate };
template <EntryType Type>
class IXQ
{
public:
virtual float GetValue() = 0;
};
class X : public IXQ<EntryType::Read>, public IXQ<EntryType::ReadUpdate>
{
public:
float IXQ<EntryType::Read>::GetValue();
/*
float IXQ<EntryType::Read>::GetValue()
{
return _x;
}
*/
float IXQ<EntryType::ReadUpdate>::GetValue();
/*
float IXQ<EntryType::ReadUpdate>::GetValue() {
_counter++;
return _x;
}
*/
float _x = 10.0F;
std::atomic<std::int32_t> _counter = 0;
};
float X::IXQ<EntryType::Read>::GetValue()
{
return _x;
}
float X::IXQ<EntryType::ReadUpdate>::GetValue()
{
_counter++;
return _x;
};
int main(int argc, char* argv[])
{
{
auto k = std::make_unique<X>();
auto ptrQ = static_cast<IXQ<EntryType::Read>*>(k.get());
std::cout << std::to_string(ptrQ->GetValue()) << std::endl;
std::cout << k->_counter.load() << std::endl;
}
{
auto k = std::make_unique<X>();
auto ptrQ = static_cast<IXQ<EntryType::ReadUpdate>*>(k.get());
std::cout << std::to_string(ptrQ->GetValue()) << std::endl;
std::cout << k->_counter.load() << std::endl;
}
return 0;
}
1. Microsoft-specific syntax
The syntax you're using to override GetValue() is not standard c++.
class X : public IXQ<EntryType::Read> {
public:
float IXQ<EntryType::Read>::GetValue() { /* ... */ }
}
This is a Microsoft-Specific Extension for C++ called Explicit Overrides (C++) and is intended to be used with __interfaces (also a microsoft-specific extension to c++).
__interfaces do not officially support c++ templates due to them being intended mostly for COM Interfaces, e.g.:
[ object, uuid("00000000-0000-0000-0000-000000000001"), library_block ]
__interface ISomething {
// properties
[ id(0) ] int iInt;
[ id(5) ] BSTR bStr;
// functions
void DoSomething();
};
It's suprising that float IXQ<EntryType::Read>::GetValue() { /* ... */ } works at all.
2. Standard C++-compliant solutions
In standard C++ the overriden function is determined by the name & arguments alone, so your only option is to override both of them.
e.g.:
class X : public IXQ<EntryType::Read>, public IXQ<EntryType::ReadUpdate>
{
public:
// will be the implementation for both IXQ<EntryType::Read> & IXQ<EntryType::ReadUpdate>
float GetValue() override;
};
float X::GetValue() {
/* ... */
}
Another standard-compliant way would be to create 2 classes that inherit from the given interfaces & then let X inherit from both of them:
class XRead : public IXQ<EntryType::Read> {
public:
float GetValue() override { /* ... */ }
};
class XReadUpdate : public IXQ<EntryType::ReadUpdate> {
public:
float GetValue() override { /* ... */ }
};
class X : public XRead, public XReadUpdate {
/* ... */
};
If you want to share state between XRead & XReadUpdate, you'd have to introduce another level, e.g.:
class XBase {
public:
virtual ~XBase() = default;
protected:
float value;
};
class XRead : public virtual XBase, public IXQ<EntryType::Read> {
float GetValue() override { return value; }
};
class XReadUpdate : public virtual XBase, public IXQ<EntryType::ReadUpdate> {
float GetValue() override { return value; }
};
class X : public XRead, public XReadUpdate {
/* ... */
};
3. Possible recommendations for API Design
Keep in mind though that this type of API design will be rather complicated to use, because you always need to cast to the specific interface first before you can call the function because X{}.GetValue() would be ambigous.
e.g.:
X x;
IXQ<EntryType::Read>& read = x;
std::cout << read.GetValue() << std::endl;
IXQ<EntryType::ReadUpdate>& update = x;
std::cout << update.GetValue() << std::endl;
// this is *not* possible, GetValue() is ambigous
// std::cout << x.GetValue() << std::endl;
I'd recommend separating both interfaces & using different method names, e.g.: godbolt example
struct IXQReadonly {
virtual ~IXQReadonly() = default;
virtual float GetValue() = 0;
};
struct IXQ : IXQReadonly {
virtual float GetValueUpdate() = 0;
};
class X : public IXQ {
public:
X() : value(0.0f), counter(0) { }
float GetValue() override { return value; }
float GetValueUpdate() override {
++counter;
return value;
}
private:
float value;
std::atomic<int> counter;
};
This comes with a whole set of benefits:
You can call GetValue() / GetValueUpdate() directly on X, no need to convert to an interface first
X x;
x.GetValue();
x.GetValueUpdate();
It is immediately clear from the method name if it will update the counter or not
A function that is given an IXQ can call a function that expects IXQReadonly, but not the other way round: (so you can "downgrade" a read-write interface to readonly, but not "upgrade" a readonly interface to read-write)
void bar(IXQReadonly& r) { r.GetValue(); /* we can't do GetValueUpdate() here */ }
void foo(IXQ& x) { bar(x); x.GetValueUpdate(); }
Additionally remember to declare the destructor as virtual (at least in the top-most class / interface), otherwise funny things tend to happen if you try to delete an instance of X through a pointer to one of its bases / interfaces.
I think this can be solved by adding an intermediate layer of classes, let's say X_Read and X_ReadUpdate from which X can inherit.
IXQ
/ \
X_Read X_ReadUpdate
\ /
X
The trick is having those intermediate classes implement GetValue by calling two virtual pure methods, let's say GetValueRead and GetValueReadUpdate respectively. This way, X still inherits from IXQ<EntryType::Read> and IXQ<EntryType::ReadUpdate>, but comes to implement GetValueRead and GetValueReadUpdate, two methods with clear and distinct interfaces.
[Demo]
template <EntryType Type>
class IXQ
{
public:
virtual float GetValue() = 0;
};
class X_Read : public IXQ<EntryType::Read>
{
public:
virtual float GetValue() override { return GetValueRead(); };
virtual float GetValueRead() = 0;
};
class X_ReadUpdate : public IXQ<EntryType::ReadUpdate>
{
public:
virtual float GetValue() override { return GetValueReadUpdate(); };
virtual float GetValueReadUpdate() = 0;
};
class X : public X_Read, public X_ReadUpdate
{
public:
virtual float GetValueRead() override { return _x; }
virtual float GetValueReadUpdate() { _counter++; return _x; };
float _x{10.0f};
std::atomic<std::int32_t> _counter{};
};
// Outputs:
// 10.000000
// 0
// 10.000000
// 1
I have a base product class with a few private members and a public getter that derived classes inherit. I would like to disqualify instantiation, since the class is intended for use with an abstract factory. I thought protected con/destructors might work, however, this breaks my smart pointers. Friending seems like a useful disaster. Is there a well-known solution to this, or should I resign myself to the fact that any client who has the factory injected must also know enough to instantiate the base product?
class Product
{
private:
char type_name;
char size_name;
public:
Product(char, char);
virtual ~Product() {}
void Print();
};
Use a token key.
private:
Product(char, char);
struct key_t{explicit key_t(int){}};
static key_t key(){return key_t(0);}
public:
Product(key_t, char a, char b):Product(a,b){}
static std::shared_ptr<Product> make_shared(char a, char b){ return std::make_shared<Product>(key(),a,b); }
anyone with a Product::key_t can construct a Product without being a friend. And without the key, you cannot.
This lets Product pass creation-rights as a value.
Smart pointers with configurable destroy code can use similar techniques. But I'd just make the destructor public.
Your static member function, or friend function, which is the factory should have no problem with calling protected constructors and returning a smart pointer. Generally plan to return a std::unique_ptr<BaseClass> which can be converted into a std::shared_ptr if the caller wants that instead.
Make the virtual destructor public.
Update: Don't bother making the factory a friend. You only need to prevent the construction of the base and intermediate classes. Make them effectively hidden and private by hiding the implementation classes in their own source file. Or an anonymous namespace I suppose.
Here have some code of how I would do it:
#include <iostream>
#include <memory>
#include <string>
// ITest is the only class any other code file should ever see.
class ITest {
protected:
ITest() = default;
public:
virtual ~ITest() = 0;
virtual int getX() const = 0;
virtual int getY() const = 0;
};
// Destructors must always have an implementation even if they are pure virtual.
ITest::~ITest() {}
std::ostream &operator<<(std::ostream &os, const ITest &x) {
return os << '[' << x.getX() << ',' << x.getY() << ']';
}
// Declaration of constructTest factory function.
// Its definition should be hidden in a cpp file.
std::unique_ptr<ITest> constructTest(int x);
// The main function does not need to know anything except the ITest interface
// class and the constructTest function declaration.
int main(int argc, char *argv[]) {
int val = 0;
if (argc > 1)
val = std::stoi(argv[1]);
auto p = constructTest(val);
std::cout << *p << std::endl;
}
// These classes should be defined in a private header file or in a cpp file.
// Should not be visible to any other code. It has no business knowing.
// Hiding all of this implementation is sort of the point of abstract interface
// classes and factory function declarations.
class TestBase : public ITest {
private:
int x = 0;
int y = 0;
protected:
TestBase(int x = 0, int y = 0) : x(x), y(y){};
public:
int getX() const override { return x; }
int getY() const override { return y; }
};
class TestA final : public TestBase {
public:
TestA() = default;
};
class TestB final : public TestBase {
public:
TestB(int x, int y) : TestBase(x, y) {}
int getX() const override { return -TestBase::getX(); }
};
std::unique_ptr<ITest> constructTest(int x) {
// make_unique is c++14.
// For C++11 use std::unique_ptr<ITest>(new TestB(x, x)
if (x) {
return std::make_unique<TestB>(x, x);
// return std::unique_ptr<ITest>(new TestB(x, x));
}
return std::make_unique<TestA>();
}
The answer was to make the destructor a pure virtual AND to implement it with an empty body. That empty implementation is where I got tripped up. Print() doesn't need to be static.
Product.hpp
#include <memory>
class Product {
public:
virtual ~Product() = 0;
void Print();
protected:
char type_name{};
char size_name{};
private:
};
Product.cpp
#include "Product.hpp"
Product::~Product() {}
void Product::Print() {
//Print p
}
This is a C++(11) question.
I have a object Obj myObj encapsulating an object f of type MyType.
Depending on runtime context, the object fshould behave differently.
One natural way of implementing this would be for the class Obj to encapsulate a pointer to an abstract base class MyType, which would, depending on the context point to different (public) child of MyType, such as MyType1, MyType2, etc.
However, I'm not very keen on Obj "suffering" the consequences of MyType being polymorphic, i.e. having to deal with a pointer. In particular, if I make it a std::unique_ptr<MyType>, it implies that Obj can either not be copied or that one needs to give it a proper copy constructor that deals with copying MyType ressources.
In my opinion, MyType being polymorphic shouldn't be Obj's problem.
I came with the following classes. Essentially the idea is to hide the pointer within MyTypeprivate attributes. In addition my second question concerns the fact that concrete implementations of MyTypeImpl may share some code shouldn't be repeated. I've put that in a class from which concrete implementations privately inherit.
I'm curious what more expert developers than me would think about it. Is it too heavy "just to hide the pointer"? Is there a better way to do it?
#include <iostream>
#include <memory>
// a "standard" implementation of MyType
class MyTypeImpl
{
public:
virtual double operator()(double a) = 0;
virtual int implType() const = 0;
virtual void complexStuff() const = 0;
};
// some internal stuff common to all implementations
class MyTypeImplInternals
{
protected:
MyTypeImplInternals(int value):factor_{value}{}
int factor_;
void longCommonFunction() const{ std::cout << "I'm doing complex stuff common to all interfaces " << factor_ << "\n" ;}
};
// one specific implementation
class MyTypeImpl1: public MyTypeImpl, private MyTypeImplInternals
{
public:
MyTypeImpl1(int factor):MyTypeImplInternals{factor}{};
virtual double operator()(double a) override {return factor_*a;}
virtual int implType() const override {return 1;}
virtual void complexStuff() const override { longCommonFunction(); }
};
// a second implementation
class MyTypeImpl2: public MyTypeImpl, private MyTypeImplInternals
{
public:
MyTypeImpl2(int factor):MyTypeImplInternals{factor}{};
virtual double operator()(double a) override {return factor_*a;}
virtual int implType() const override {return 2;}
virtual void complexStuff() const override { longCommonFunction(); }
};
class MyTypeImplFactory
{
public:
static std::unique_ptr<MyTypeImpl>createMyTypeImpl(int implementationType)
{
switch(implementationType)
{
case 1:
return std::unique_ptr<MyTypeImpl> (new MyTypeImpl1(12));
case 2:
return std::unique_ptr<MyTypeImpl> (new MyTypeImpl2(22));
default:
throw std::runtime_error("implementation does not exist...\n");
return nullptr;
}
}
};
// my type
class MyType
{
public:
MyType(int implementationType)
{
implPtr_ = MyTypeImplFactory::createMyTypeImpl(implementationType);
}
MyType(MyType const& source)
: implPtr_{ MyTypeImplFactory::createMyTypeImpl(source.implType()) }
{
}
double operator()(double a){return (*implPtr_)(a);}
int implType() const {return implPtr_->implType();}
void complexStuff() const {implPtr_->complexStuff();}
private:
std::unique_ptr<MyTypeImpl> implPtr_;
};
class Obj
{
private:
MyType f;
public:
Obj(int dim):f{dim}{}
Obj(Obj&& sourceToMove) = default;
Obj(Obj const& source) = default;
void doStuff() {std::cout << "I'm doing stuff() " << f(2) << std::endl; f.complexStuff();}
};
int main()
{
Obj myObj{1}, myObj2{2};
myObj.doStuff();
myObj2.doStuff();
Obj myObj3{std::move(myObj2)}; // myObj2 now dead
Obj myObj4{myObj};
myObj3.doStuff();
myObj4.doStuff();
}
link to online compiler : http://cpp.sh/8rhyy
Here the implementations are very dumb ones to serve as an example. An application for this design could be for instance a Solver (Obj) that solves some kind of physics Equation (MyType) which exact definition depends on the dimensionality of the problem, equation in 1D space is not the same as in 2D or in 3D. Solver's code would be completely independent on Equation's dimensionality and also wouldn't have to deal with a pointer. Equation would hide its 1D, 2D, or 3D implementation from outside's world.
(was originally a post on code review that was put on Hold because to abstract)
This proposed class design appears to have an obvious problem. The polymorphic type is referenced by a std::unique_ptr:
std::unique_ptr<MyTypeImpl> implPtr_;
Obj's default copy constructor, and assignment operator will end up transferring the held pointer to the new object, leaving the std::unique_ptr in the original object staring at a nullptr. Not good.
At the bare minimum this should be either a std::shared_ptr, or Obj's copy constructor and assignment operator will need to instantiate a new implPtr_. Note that with the easy std::shared_ptr fix the result of the copy constructor and an assignment operator is having multiple instances of Obj referencing the same instance of MyTypeImpl, which may or may not be an issue.
A much simpler class design is simply have MyTypeImpl1 and MyTypeImpl2 be subclasses of Obj, implementing the required polymorphic behavior.
I just refactored your codes.
#include <iostream>
#include <memory>
// !abstraction
class MyType
{
public:
virtual double operator()(double a) = 0;
virtual int implType() const = 0;
virtual void complexStuff() const = 0;
};
// !!MyTypeImplInternals could be a super class of MyTypeImpl* if it has properties(such as factor_) or just some static functions.
class MyTypeImplInternals
{
public:
MyTypeImplInternals(int value):factor_{value}{}
int factor_;
void longCommonFunction() const{ std::cout << "I'm doing complex stuff common to all interfaces " << factor_ << "\n" ;}
};
// one specific implementation
class MyTypeImpl1: public MyType
{
MyTypeImplInternals internal_;
public:
MyTypeImpl1(int factor):internal_{factor}{};
virtual double operator()(double a) override {return internal_.factor_*a;}
virtual int implType() const override {return 1;}
virtual void complexStuff() const override { internal_.longCommonFunction(); }
};
// a second implementation
class MyTypeImpl2: public MyType
{
MyTypeImplInternals internal_;
public:
MyTypeImpl2(int factor):internal_{factor}{};
virtual double operator()(double a) override {return internal_.factor_*a;}
virtual int implType() const override {return 2;}
virtual void complexStuff() const override { internal_.longCommonFunction(); }
};
std::unique_ptr<MyType> createMyType(int implementationType)
{
switch(implementationType)
{
case 1:
return std::unique_ptr<MyType> (new MyTypeImpl1(12));
case 2:
return std::unique_ptr<MyType> (new MyTypeImpl2(22));
default:
throw std::runtime_error("implementation does not exist...\n");
return nullptr;
}
}
class Obj
{
private:
std::unique_ptr<MyType> f_;
public:
Obj(int dim):f_(createMyType(dim)){}
Obj(Obj&& sourceToMove) : f_(std::move(sourceToMove.f_)) {}
Obj(Obj const& source) : f_(createMyType(source.f_->implType())) {}
void doStuff() {std::cout << "I'm doing stuff() " << (*f_)(2) << std::endl; f_->complexStuff();}
};
int main()
{
Obj myObj{1}, myObj2{2};
myObj.doStuff();
myObj2.doStuff();
Obj myObj3{std::move(myObj2)}; // myObj2 now dead
Obj myObj4{myObj}; //!!Bad idea to share an implementation to more Objs.
myObj3.doStuff();
myObj4.doStuff();
}
Here is the header file defining the template:
Based on a few answers, I made modifications to make template single thread safe. But the program still crashes, so I believe the focus here should not be if the template is thread safe. It's about what happened when C1 inherits from both CBase and Singleton. Apparently, the program crashes when C1 is trying to call the function of the member variable it's parent Class CBase. It seems to me, something is messed up in the memory when multiple inheritance and the single template are used together.
#ifndef _T_SINGLETON_HH_
#define _T_SINGLETON_HH_
template <class T>
class Singleton
{
public:
static T* getInstance()
{
static T instance_;
return &instance_;
}
template <class A>
static T* getInstance(A a)
{
static T instance_(a);
return &instance_;
}
protected:
Singleton() {}
virtual ~Singleton() {}
private:
Singleton(Singleton const&);
Singleton& operator=(Singleton const&);
};
#endif // _T_SINGLETON_HH_ //
And here is how this template was used:
#include <iostream>
#include <unistd.h>
#include <pthread.h>
#include "singleton.hh"
using namespace std;
class X;
class X1;
class ABase;
class BBase;
class BB;
class CBase;
class X {
public:
virtual int getX() = 0;
};
class X1 : public X {
public:
int getX() { return 1; }
};
class Timer
{
private:
static Timer* t_;
BBase* b_;
Timer();
static void* go_helper(void* context);
void go();
public:
virtual ~Timer() {}
static Timer* getInstance();
void subscribe(BBase* b);
void unsubscribe(BBase* b) { b_ = NULL; }
};
class CBase {
public:
CBase(BB& bb) : bb_(bb) {}
virtual void run() = 0;
protected:
BB& bb_;
};
class C1 : public CBase,
public Singleton<C1>
{
public:
C1(BB& bb) : CBase(bb) {}
void run();
};
class BBase {
public:
BBase(ABase& a) : a_(a) { Timer::getInstance()->subscribe(this); }
virtual ~BBase() { Timer::getInstance()->unsubscribe(this); }
virtual void run() = 0;
protected:
ABase& a_;
};
class BB : public BBase {
public:
BB(ABase& a) : BBase(a) {
c = C1::getInstance(*this);
// c = new C1(*this); IF WE USE THIS INSTEAD, THEN IT WILL WORK
}
int getX();
void run();
private:
CBase* c;
};
class ABase {
public:
ABase() {
x = new X1;
b = new BB(*this);
}
void run();
int getX() { return x->getX(); }
private:
X* x;
BBase* b;
};
Timer* Timer::t_ = NULL;
Timer::Timer() : b_(NULL)
{
pthread_t th;
pthread_create(&th, NULL, &Timer::go_helper, this);
}
Timer*
Timer::getInstance() {
if (t_ == NULL)
t_ = new Timer;
return t_;
}
void
Timer::subscribe(BBase* b) { b_ = b; }
void*
Timer::go_helper(void* context) {
Timer *t = reinterpret_cast<Timer*>(context);
t->go();
return NULL;
}
void
Timer::go()
{
while(1) {
sleep(1);
if (b_) b_->run();
}
}
void ABase::run() {
cout << __PRETTY_FUNCTION__ << getX() << endl;
cout << __PRETTY_FUNCTION__ << x->getX() << endl;
b->run();
while(1)
sleep(1);
}
int BB::getX() {
return a_.getX();
}
void BB::run() {
cout << __PRETTY_FUNCTION__ << endl;
c->run();
}
void C1::run() {
cout << __PRETTY_FUNCTION__ << bb_.getX() << endl;
}
int main()
{
ABase* a = new ABase;
a->run();
}
If you still think it is a thread safe issue, then here is the simplified one thread version using the template:
#include <iostream>
#include <unistd.h>
#include <pthread.h>
#include "singleton.hh"
using namespace std;
class X;
class X1;
class ABase;
class BBase;
class BB;
class CBase;
class X {
public:
virtual int getX() = 0;
};
class X1 : public X {
public:
int getX() { return 1; }
};
class CBase {
public:
CBase(BB& bb) : bb_(bb) {}
virtual void run() = 0;
protected:
BB& bb_;
};
class C1 : public CBase,
public Singleton<C1>
{
public:
C1(BB& bb) : CBase(bb) {}
void run();
};
class BBase {
public:
BBase(ABase& a) : a_(a) { }
virtual ~BBase() { }
virtual void run() = 0;
protected:
ABase& a_;
};
class BB : public BBase {
public:
BB(ABase& a) : BBase(a) {
c = C1::getInstance(*this);
// c = new C1(*this);
}
int getX();
void run();
private:
CBase* c;
};
class ABase {
public:
ABase() {
x = new X1;
b = new BB(*this);
}
void run();
int getX() { return x->getX(); }
private:
X* x;
BBase* b;
};
void ABase::run() {
cout << __PRETTY_FUNCTION__ << getX() << endl;
cout << __PRETTY_FUNCTION__ << x->getX() << endl;
b->run();
while(1)
sleep(1);
}
int BB::getX() {
return a_.getX();
}
void BB::run() {
cout << __PRETTY_FUNCTION__ << endl;
c->run();
}
void C1::run() {
cout << __PRETTY_FUNCTION__ << bb_.getX() << endl;
}
When I run this program, it crashes:
void ABase::run()1
void ABase::run()1
virtual void BB::run()
zsh: segmentation fault (core dumped) ./a.out
Here is the stack information given by GDB:
#0 0x00000000004012ba in ABase::getX (this=0x1) at tst_sigill.cc:89
89 int getX() { return x->getX(); }
[Current thread is 1 (Thread 0x7faa0f050740 (LWP 5351))]
(gdb) bt
#0 0x00000000004012ba in ABase::getX (this=0x1) at tst_sigill.cc:89
#1 0x0000000000400e0c in BB::getX (this=0x7ffed6e821f0) at tst_sigill.cc:138
#2 0x0000000000400e71 in C1::run (this=0xaeedd0) at tst_sigill.cc:146
#3 0x0000000000400e51 in BB::run (this=0xaeec60) at tst_sigill.cc:142
#4 0x0000000000400de3 in ABase::run (this=0xaeec20) at tst_sigill.cc:132
#5 0x0000000000400ed1 in main () at tst_sigill.cc:152
For some unknown reason, this pointer passed to BB::getX and ABase::getX was messed up. I can't see what's wrong with the code.
Well, the major problem seems to be that your getInstance() implementation isn't thread safe.
I'd recommend forgetting about all that construct() / destruct() stuff also and simply leave that to the CRT0 code provided with the ABI.
You should rather use an implementation following the Scott Meyer's Singleton that is guaranteed to be thread safe (at least for the current standard):
template <class T>
class Singleton {
public:
static T& getInstance() {
static T instance_;
return instance_;
}
protected:
Singleton() {}
virtual ~Singleton() {}
Singleton(Singleton const&) = delete;
Singleton& operator=(Singleton const&) = delete;
};
If there's need to change any of the Singletons properties later that could be accessed asynchronously, keep in mind to provide thread safe operations as well.
You could support that with your template singleton base like:
template <class T>
class Singleton {
// ...
protected:
mutable std::mutex internalDataGuard;
};
class C1 : public CBase, public Singleton<C1> {
public:
C1(BB& bb) : CBase(bb) {}
void run();
void setSomeData(T data) {
std::unique_lock(Singleton<C1>::internalDataGuard);
// change internal data member ...
}
const T& getSomeData() const {
std::unique_lock(Singleton<C1>::internalDataGuard);
// return internal data member ...
}
};
A quick note on using the stack trace to pick off some useful information. The program crashes where it crashes, but sometimes the trace can give you a few hints on where things started to go wrong:
#0 0x00000000004012ba in ABase::getX (this=0x1) at tst_sigill.cc:89
Died here. this=0x1, says that this is pointing to nonsense; 0x1 is almost certainly an invalid memory location. I can't think of a modern platform where 1 is valid memory. Doesn't mean there isn't one, but it's highly unlikely and thus a suspect.
#1 0x0000000000400e0c in BB::getX (this=0x7ffed6e821f0) at tst_sigill.cc:138
Here this is questionable. Skipping down over the next few lines, we see that all of the this pointers are in and around 0xaeeXXX. 0x7ffed6e821f0 is pretty far out there, so we should start by looking at references to BB
#2 0x0000000000400e71 in C1::run (this=0xaeedd0) at tst_sigill.cc:146
Specifically those inside C1 since it was the last object we were in with a sane address.
Maybe the rest of the stack trace matters, maybe it doesn't. Maybe we'll get back to it for more clues, but for the moment let's run down the current leads.
Looking in on C1, I see:
C1(BB& bb) : CBase(bb) {}
Takes a BB reference and passes it to CBase's constructor
CBase(BB& bb) : bb_(bb) {}
Stores the BB in bb_
So where does the BB come from? C1 is instantiated by the singleton. I don't see any calls to construct, so this leaves getInstance(A a), which does not take a reference. This means C1(BB& bb) is called with a temporary. The temporary is ultimately stored in CBase::bb_ which is a BB&, so bb_ is a reference to a variable that will no longer exist after returning from getInstance. Attempting to use bb_ after this point will invoke Undefined Behaviour.
I am not going to suggest a fix for this because this code is too convoluted for it's own good and, as πάντα ῥεῖ points out in his answer, isn't going to work without a significant redesign.
Edit: Per some comments, by simple I mean a) less code, b) easy to maintain, and c) hard to get wrong.
Edit #2: Also, using containment instead of private inheritance is not objectionable if it does indeed simplify the implementation of InterfaceImpl.
Currently, the only way I know to do this is to have the implementer define the abstract method and delegate the call to the target base type's method. Example:
#include <iostream>
#include <memory>
class Interface
{
public:
virtual void method1() = 0;
virtual void method2(int x) = 0;
};
class MethodOneImpl
{
private:
void method1(int x)
{ std::cout << "MethodOneImpl::method1() " << x << std::endl; }
public:
void method1() { method1(0); }
};
class MethodTwoImpl
{
public:
void myFunc(int x)
{ std::cout << "MethodTwoImpl::myFunc(x)" << x << std::endl; }
};
class InterfaceImpl : public Interface
, private MethodOneImpl
, private MethodTwoImpl
{
public:
virtual void method1() { MethodOneImpl::method1(); }
virtual void method2(int x) { MethodTwoImpl::myFunc(x); }
};
int main()
{
std::unique_ptr<Interface> inf;
inf.reset(new InterfaceImpl);
inf->method1();
inf->method2(0);
// This should be disallowed!
// std::unique_ptr<MethodOneImpl> moi;
// moi.reset(new InterfaceImpl);
}
At first, I thought that perhaps this might solve the problem:
class InterfaceImpl : public Interface
, private MethodOneImpl
, private MethodTwoImpl
{
public:
using MethodOneImpl::method1;
// Obviously this wouldn't work as the method names don't match.
//using MethodTwoImpl::???
};
The first using statement will make both MethodOneImpl::method1 methods be public, but it actually doesn't fulfill the contract with Interface, and it modifies the accessibility of MethodOneImpl::method1(int). And obviously we couldn't use this solution with method2 as the names don't match up.
FWIW, I have what I think is a solution, but it is not part of the standard at all (in other words it won't compile). I was thinking of making a proposal to the C++ committee; if anyone has any advice, I'd appreciate any comments below (but please dont' submit the advice as an answer).
An other option (at least if using MS VC++) is to use virtual inheritance:
struct MyInterface
{
virtual void Method1() = 0;
virtual void Method2() = 0;
};
class Method1Impl : public virtual MyInterface
{
virtual void Method1() { _tprintf( _T("Method1\n") ); }
};
class Method2Impl : public virtual MyInterface
{
virtual void Method2() { _tprintf( _T("Method2\n") ); }
};
class InterfaceImpl : public virtual MyInterface,
private Method1Impl,
private Method2Impl
{
};
void TestWeirdInterfaceImpl()
{
MyInterface* pItf = new InterfaceImpl();
pItf->Method1();
pItf->Method2();
}
While this seems to work and satisfy what you are looking for (asside from C4250 warning that you will have to suppress with a #pragma), this wouldn't be my approach. (I believe virtual inheritance is still not something that supported across all compilers, but I could be wrong).
I would probably go with containment and once boilerplate code is identifier, wrap it into some kind of macro map (similar to maps in ATL or MFC) that would make it really, really difficult to ever screw it up.
So this would be my macro approach:
struct MyInterface
{
virtual float Method1( int x ) = 0;
virtual int Method2( float a, float b ) = 0;
virtual void Method3( const TCHAR* sz ) = 0;
};
class Method1Impl
{
public:
float Method1( int x ) {
_tprintf( _T("Method1: %d\n"), x ); return 5.0;
}
};
class Method2and3Impl
{
public:
int Method2( float a, float b ) {
_tprintf( _T("Method2: %f, %f\n"), a, b ); return 666;
}
void Method3( const TCHAR* sz ) {
_tprintf( _T("Method3: %s"), sz );
}
};
#define DECLARE_METHOD0( MethodName, Obj, R ) \
virtual R MethodName() { return Obj.MethodName(); }
#define DECLARE_METHOD1( MethodName, Obj, R, A1 ) \
virtual R MethodName( A1 a1 ) { return Obj.MethodName( a1 ); }
#define DECLARE_METHOD2( MethodName, Obj, R, A1, A2 ) \
virtual R MethodName( A1 a1, A2 a2 ) { return Obj.MethodName( a1, a2 ); }
class InterfaceImpl : public MyInterface
{
public:
DECLARE_METHOD1( Method1, m_method1Impl, float, int );
DECLARE_METHOD2( Method2, m_method2and3Impl, int, float, float );
DECLARE_METHOD1( Method3, m_method2and3Impl, void, const TCHAR* );
private:
Method1Impl m_method1Impl;
Method2and3Impl m_method2and3Impl;
};
void TestWeirdInterfaceImpl()
{
MyInterface* pItf = new InterfaceImpl();
pItf->Method1( 86 );
pItf->Method2( 42.0, 24.0 );
pItf->Method3( _T("hi") );
}
Until C++ gods grace us with variadic macros, you'll have to declare one for each number of parameters you have. Also if you used multiple inheritance, potentially you wouldn't need the second "Obj" param, but as I've said before, I'd avoid multiple inheritance if there's another solution, which in this case is one extra param.
Yet a third option could be something that authors of Pragmatic Programmer seem to advocate a lot. If you have a ton of cookie cutter code that you don't want to repeat because, as you pointed out, it introduces human error. Define your own language and write a code generator script (python, perl...) to auto-create the actual code. In this case you could almost point at an interface, and have the script write the text out for you. I haven't tried doing this kind of thing myself, but lately have been wanting to use it somewhere just to see and evaluate the outcome.
This is sort of ugly and may bloat the executable size, but what about
#include <iostream>
class Interface
{
public:
virtual void method1() = 0;
virtual void method2(int x) = 0;
};
template<typename T>
class MethodOneImpl : public T
{
private:
void method1(int x)
{ std::cout << "MethodOneImpl::method1() " << x << std::endl; }
public:
void method1() { method1(0); }
};
template<typename T>
class MethodTwoImpl : public T
{
public:
void method2(int x)
{ std::cout << "MethodTwoImpl::myFunc(x)" << x << std::endl; }
};
class InterfaceImpl : public MethodTwoImpl<MethodOneImpl<Interface> >
{
};
int main()
{
InterfaceImpl impl;
impl.method1();
impl.method2(0);
}
class AbsInterface
{
// this is a simple interface class.
public:
virtual void Method1() = 0;
virtual void Method2() = 0;
};
class Functor1
{
public:
void operator () ()
{
printf("This Is Void Functor1");
}
};
class Functor2
{
public:
void operator () ()
{
printf("This Is void Functor2");
}
};
template <class T1, class T2>
class DerivedTemplateClass : public AbsInterface
{
public:
virtual void Method1() { T1()(); }
virtual void Method2() { T2()(); }
};
void main()
{
DerivedTemplateClass<Stratege1, Stratege2> instance;
instance.Method1();
instance.Method2();
}
as you can see, I used Functor.
You could work with template and functor.
It seems impossible to bring MethodOneImpl / MethodTwoImpl into the scope of Interface without having them inherit from Interface because they will not fill the Virtual Table if they don't. C++ misses something like the keyword implements from other languages.
So you are stuck with the virtual inheritence thing unless realize/accept that what you are looking for is just a bridge pattern, which does not satisfy requirement a) (you shall write more code), midly b) (code not necessarly difficult to maintain) and may satisfy c).
Here (another) possible solution (with only method though to reduce bloat)
class Interface
{ public:
virtual void method1() {return impl_->method1();}
private:
Interface() {}
protected:
struct Impl {
virtual void method1() = 0; };
std::shared_ptr<Impl> impl_;
Interface(const std::shared_ptr<Impl> &impl) : impl_(impl) {}
};
class InterfaceImpl : public Interface
{
struct Impl : public Interface::Impl {
void method1() { std::cout << "InterfaceImpl::method1() " << std::endl; } } ;
public:
InterfaceImpl() : Interface(std::shared_ptr<Impl> (new Impl)) {}
};
template <class T>
class GenericInterfaceImpl : public Interface {
struct Impl : public Interface::Impl {
Impl( T &t) : t_(t) {}
void method1() { t_.method1() ; }
T t_; };
public:
GenericInterfaceImpl() : Interface(std::shared_ptr<Impl> (new Impl(T()))) {}
};
struct AMethod1Impl {
void method1() { std::cout << "AMethod1Impl::method1() " << std::endl; } } ;
struct AnotherMethod1Impl_not_working {
void method1_not_present() { std::cout << "AnotherMethod1Impl_not_working ::method1_not_present() " << std::endl; } } ;
int main() {
// compilation of next line would fail
// (lame attempt to simulate ompilation fail when pure function not implemented)
// Interface inf;
std::unique_ptr<Interface> inf;
inf.reset(new InterfaceImpl);
inf->method1();
inf.reset(new GenericInterfaceImpl<AMethod1Impl>() );
inf->method1();
// compilation of next line would fail
// inf.reset(new GenericInterfaceImpl<AnotherMethod1Impl_not_working>() );
}
Does this serve your purpose?
It maintains the interface relationship and gives you maintainable code without having any consideration of client code.
Separating each method in functionoid and giving you the power to control the prototype of each method of the different base class.
#include <iostream>
#include <memory>
using namespace std;
//No Control over this.
class MethodOneImpl
{
private:
void method1(int x)
{ std::cout << "MethodOneImpl::method1() " << x << std::endl; }
public:
void method1() { method1(0); }
};
class MethodTwoImpl
{
public:
void myFunc(int x)
{ std::cout << "MethodTwoImpl::myFunc(x)" << x << std::endl; }
};
//*************************//
class Interface
{
public:
virtual void method1() = 0;
virtual void method2(int x) = 0;
};
//This is what i would do. //
class BaseFuncType
{
//no pure virtual
void Call()
{
throw "error";
}
void Call(int x)
{
throw "error";
}
};
class Method1: public BaseFuncType
{
auto_ptr<MethodOneImpl> MethodPtr;
public:
Method1()
{
MethodPtr.reset(new MethodOneImpl());
}
virtual int Call()
{
MethodPtr->method1();
}
};
class Method2: public BaseFuncType
{
auto_ptr<MethodTwoImpl> MethodPtr;
public:
Method2()
{
MethodPtr.reset(new MethodTwoImpl());
}
virtual int Call(int x)
{
MethodPtr->myFunc(x);
}
};
template <class T1>
class MethodFactory
{
private:
T1 methodObj;
public:
void CallMethod()
{
methodObj.Call();
}
void CallMethod(int x)
{
methodObj.Call(x);
}
};
class InterfaceImpl : public Interface
{
auto_ptr<MethodFactory> factory;
public:
virtual void method1()
{
factory.reset(new MethodFactory<Method1>());
factory->CallMethod();
}
virtual void method2(int x)
{
factory.reset(new MethodFactory<Method2>());
factory->CallMethod(x);
}
};
int main()
{
auto_ptr<Interface> inf;
inf.reset(new InterfaceImpl);
inf->method1();
inf->method2(10);
// This should be disallowed!
// std::unique_ptr<MethodOneImpl> moi;
// moi.reset(new InterfaceImpl);
}