I use a third party library over which I have no control. It contains 2 classes A and B, which both define a method with the same name:
class A {
public:
...
void my_method ();
};
class B {
public:
...
void my_method ();
};
I want to create a class C that contains a member which is of class A or B. Crucially, I can know only at runtime whether I will need A or B. This class C will only call the method my_method.
If I could modify the code, I would simply make A and B derive from a parent class (interface) that defined my_method. But I can't.
What is the simplest/most elegant way to create this class C? I could of course define C in this way:
class C {
public:
void call_my_method() { if (a) a->my_method() else b->my_method(); }
private:
A* a;
B* b;
But I want to avoid paying the cost of the if statement everytime. It also feels inelegant. Is there a way I can create a super type of class A or B? Or any other solution to this problem?
You may use std::function (not sure it has better performance though), something like:
class C {
public:
void call_my_method() { my_method(); }
void use_a(A* a) { my_method = [=]() { a->my_method() }; }
void use_b(B* b) { my_method = [=]() { b->my_method() }; }
private:
std::function<void()> my_method;
};
No; at some point you need branching. The best you can do is to hoist the branching up/down the call stack†, so that more of your program is encapsulated within the figurative if/else construct and the branch itself need be performed less frequently. Of course then you need to duplicate more of your program's source code, which is not ideal.
The only improvement I'd suggest at this time is a construct such as boost::variant. It basically does what you're already doing, but takes up less memory and doesn't have that layer of indirection (using what's called a tagged union instead). It still needs to branch on access, but until profiling has revealed that this is a big bottleneck (and you'll probably find that branch prediction alleviates much of this risk) I wouldn't go any further with your changes.‡
† I can never remember which way it goes lol
‡ One such change might be to conditionally initialise a function pointer (or modern std::function), then call the function each time. However, that's a lot of indirection. You should profile, but I'd expect it to be slower and harder on the caches. An OO purist might recommend a polymorphic inheritance tree and virtual dispatch, but that's not going to be of any use to you once you care about performance this much.
How about using inheritance with a virtual function, using a 'base class' (C):
class C
{
public:
virtual void do_method() = 0;
};
class D : public C, private A
{
void do_method() { my_method(); }
};
class E : public C, private B
{
void do_method() { my_method(); }
}
Then this will work:
C * d = new D();
d->do_method();
Suggest to wrap your A and B objects into some helper template TProxy which realizes IProxy interface. Class C (or Consumer) will work with IProxy interface and won't know about type of the object inside Proxy
#include <stdio.h>
struct A {
void func () { printf("A::func\n"); }
};
struct B {
void func () { printf("B::func\n"); }
};
struct IProxy
{
virtual void doFunc() = 0;
virtual ~IProxy() {};
};
template<typename T>
struct TProxy : public IProxy
{
TProxy(T& i_obj) : m_obj(i_obj) { }
virtual void doFunc() override { m_obj.func(); }
private:
T& m_obj;
};
class Consumer
{
public:
Consumer(IProxy& i_proxy) : m_proxy(i_proxy) {}
void Func() { m_proxy.doFunc();}
private:
IProxy& m_proxy;
};
Main:
int main()
{
A a;
TProxy<A> aProxy(a);
B b;
TProxy<B> bProxy(b);
Consumer consumerA{aProxy};
consumerA.Func();
Consumer consumerB{bProxy};
consumerB.Func();
return 0;
}
Output:
A::func
B::func
Related
I need a way to provide different interfaces from a single object.
For example. User one should be able to call Foo::bar() and user 2 should be able to call Foo::baz() but user one cannot call Foo::baz() and respectively user two cannot call Foo::bar().
I did manage to do this but I don't think that it's optimal.
class A
{
public:
virtual void bar() = 0;
virtual ~A() = 0;
};
class B
{
public:
virtual void baz() = 0;
virtual ~B() = 0;
};
class Foo : public A, public B
{
public:
Foo() = default;
void baz() override;
void bar() override;
};
class Factory
{
public:
Factory()
{
foo = std::make_shared<Foo>();
}
std::shared_ptr<A> getUserOne()
{
return foo;
}
std::shared_ptr<B> getUserTwo()
{
return foo;
}
private:
std::shared_ptr<Foo> foo;
};
Is there a better way to achieve this. Maybe with wrapper objects. I don't really need to allocate this foo object with new(std::make_shared) I even prefer not to, but I cannot use raw pointers and smart pointers give unnecessary overhead and system calls.
Edit: I'll try to give an example.
There is a car. User one is the driver. He can steer the wheel, accelerate or use the breaks. User two is the passenger and he can control the radio for example.
I don't want the passenger to be able to use the breaks or the driver to be able to use the radio.
Also they are both in the car so the actions of user one will have effect on user two and vice versa.
What you essentially need is a shared data between two objects. The inheritance is not a very good choice for this because not only you do not need is A relationship but you explicitely want to avoid it. Therefore composition is your answer, especially since you have a factory:
class Data
{
public:
void bar();
void baz();
};
Then instead of inheritance you would use composition:
class A
{
public:
A(Base *base) : mBase(base) {}
void bar() { mBase->bar(); }
private:
Base *mBase = nullptr;
};
//class B would be the same only doing baz()
Finally the Factory:
class Factory
{
public:
A *getUserOne() { return &mA; }
B *getUserTwo() { return &mB; }
private:
Base mBase;
A mA(&mBase);
B mB(&mBase);
};
Couple of points about this solution. While it does not allocate on the heap you will need to keep the Factory alive as long as there are users of it. For this reason the use of std::shared_ptr as in the OP might be a smart idea. :-) But comes of course with the cost of the atomic reference counting.
Secondly A is not related to B in any way. This is by design and unlike the original solution does not allow dynamic_cast between A and B.
Lastly where the implementation will be is up to you. You can have it all in Data and have A and B merely call it (as in above) but you can also make Data into just a struct holding only your data and have the implementation of your methods in A and B respectively. The latter is more "data oriented" programming that has a lots of popularity these days as opposed to more traditional "object oriented" which is what I chose to demonstrate.
You can declare your data separately
struct Data
{
/* member variables */
};
Have an interface class capable of manipulating said data will all members protected
class Interface
{
protected:
Interface(Data &data) : m_data{data} {}
void bar() { /* implementation */ }
void baz() { /* implementation */ }
Data &m_data;
};
Have derived classed that make public specific members
class A : private Interface
{
public:
A(Data &data) : Interface{data} {}
using Interface::bar;
};
class B : private Interface
{
public:
B(Data &data) : Interface{data} {}
using Interface::baz;
};
This way you can also have users capable of having overlapping access to some functionality without having to implement it multiple times.
class Admin : private Interface
{
public:
Admin(Data &data) : Interface{data} {}
using Interface::bar;
using Interface::baz;
};
Of course, depending on how you're using the data, you might want a pointer or shared pointer, possibly add some syncronization between accesses from multiple threads.
Sample code using this model:
void test()
{
Data d{};
auto a = A{d};
a.bar();
// a.baz is protected so illegal to call here
auto b = B{d};
b.baz();
// b.bar is protected so illegal to call here
auto admin = Admin{d};
admin.bar();
admin.baz();
}
This seems to me efficient in the sense that you only have one set of data and a single implementation for data manipulation, no matter how many user types you have.
I want a function return its real type, even it called in subclass. Here is the test code:
class Super
{
public:
Super(){};
virtual auto getSelf() -> decltype(*this)&
{
return *this;
}
void testSuper(){};
};
class Sub : public Super
{
public:
void testSub(){};
};
int main()
{
Sub().getSelf().testSuper();//OK
//Sub().getSelf().testSub();//Error
return 0;
}
In Objective-C, I can use instanttype to solve this.
But in C++, is it possible?
By the way, I do not want a template implementation, since it may increase the code size.
But in C++, is it possible?
Yes, and just like anything in C++, there is many ways to do it. But both ways require you to add something in the Sub class.
If you don't need virtual functions, then simply override (statically) that function:
struct Super {
auto getSelf() -> Super& {
return *this;
}
void testSuper(){};
};
struct Sub : Super {
auto getSelf() -> Sub& {
return *this;
}
void testSub(){};
};
int main() {
Sub().getSelf().testSuper(); //OK
Sub().getSelf().testSub(); //OK too!
return 0;
}
Of course, if you don't like copy pasting that code, you can always create a mixin class (a CRTP template):
template<typename Subclass>
struct AddGetSelf {
auto getSelf() -> Subclass& {
return static_cast<Subclass&>(*this);
}
};
You can the use that mixin in your classes like this:
struct Super : AddGetSelf<Super> {
using AddGetSelf<Super>::getSelf;
void testSuper(){};
};
struct Sub : Super, AddGetSelf<Sub> {
using AddGetSelf<Sub>::getSelf;
void testSub(){};
};
If you need virtual polymorphism, you can rely on covariant return types:
struct Super {
virtual auto getSelf() -> Super& {
return *this;
}
void testSuper(){};
};
struct Sub : Super {
auto getSelf() -> Sub& override {
return *this;
}
void testSub(){};
};
int main() {
Sub().getSelf().testSuper(); //OK
Sub().getSelf().testSub(); //OK too!
return 0;
}
Here's a live example at Coliru
If you are worried about binary size, consider static linking and link time optimisation.
I suggest you to try out both solutions and compare binary sizes, since template size increase can be cancelled out by compiler optimisation, and virtual polymorphism can prevent the compiler to do these optimisations.
I am going to go ahead with no. There is not convenient mechanisms in c++ to perform what you wish. (By convenient I mean avoiding any boilerplate, IMO options presented by Guillaume in his answer are certainly worth exploring.)
The code for different cases has to be duplicated. Types and objects cannot be created during run-time, like e.g. in C#. So you have to have code for each type.
You can do what you wish through static polymorphism, though those are templates. Maybe the compiler is smart enough to optimize each copy of getSelf, after all it's all returning the same pointer. But from the language point of view you have to provide a definition for each type.
There is run-time type information, but you would still need to if between the types effectively duplicating the code.
You might implement your example pure run-time using RTTI and dynamic cast, but it would be kinda ugly, as you would have to cast to reference manually... and dangerous.
E.g:
#include <iostream>
class Super
{
public:
Super(){};
virtual auto getSelf() -> decltype(*this)&
{
return *this;
}
void testSuper(){};
};
class Sub : public Super
{
public:
void testSub(){std::cout << "test\n"; };
};
int main()
{
Sub().getSelf().testSuper();//OK
dynamic_cast<Sub&>(Sub().getSelf()).testSub();//Danger
return 0;
}
But in C++, is it possible?
Short answer is - not directly as it happens in C#.
The type of this is the one of a pointer to the type of the subobject that offers the member function definition.
That is, Super * within getSelf definition in Super, Sub * within getSelf definition in Sub.
That said, note that the goal of double dispatching matches your requirements.
The drawback is that a call like Sub().getSelf().method(); is not possible anymore in this case.
It follows a minimal, working example:
struct Visitor;
struct Super
{
virtual void getSelf(Visitor &) = 0;
void testSuper(){}
};
struct Sub : Super
{
void getSelf(Visitor &) override;
void testSub(){}
};
struct Visitor
{
void accept(Sub &sub)
{
sub.testSuper();
sub.testSub();
}
};
void Sub::getSelf(Visitor &v)
{
v.accept(*this);
}
int main()
{
Visitor visitor;
Sub sub;
Super &super = sub;
super.getSelf(visitor);
}
What you want to be done as in Object-C is not possible in C++. They have different object calling models. See Object-C Messages. When you call object in C++ compiler must know everything about member function at compile time. In Object-C you don't call member function directly you send message to the object. So this is run-time binding.
I have a class (let's call it A) the inherits an interface defining several abstract methods and another class there to factor in some code (let's call it B).
The question is, I have an abstract method in the interface that A implements just to call the B version. Is there a way to use the keyword using to avoid writing a dull method like:
int A::method() override
{
return B::method();
}
I tried writing in A using B::method, but I still get an error that A doesn't implement the abstract method from the interface.
Is there a special technique to use in the case or am I just out of luck? (and if so, is there a specific reason why it should be that way?).
Thanks.
edit:
To clarify, the question is, why isn't it possible to just do this:
class A: public Interface, public B {
using B::method;
};
Let's make this clear. You basically have the following problem, right?
struct Interface
{
virtual void method() = 0;
};
struct B
{
void method()
{
// implementation of Interface::method
}
};
struct A : Interface, B
{
// some magic here to automatically
// override Interface::method and
// call B::method
};
This is simply impossible, because the fact that the methods have the same names is irrelevant from a technical point view. In other word's, Interface::method and B::method are simply not related to each other, and their identical names are not more than a coincidence, just like someone else called "Julien" doesn't have anything to do with you just because you share the same first name.
You are basically left with the following options:
1.) Just write the call manually:
struct A : Interface, B
{
virtual void method()
{
B::method();
}
};
2.) Minimise writing work with a macro, so that you can write:
struct A : Interface, B
{
OVERRIDE(method)
};
But I would strongly recommend against this solution. Less writing work for you = more reading work for everyone else.
3.) Change the class hierarchy, so that B implements Interface:
struct Interface
{
virtual void method() = 0;
};
struct B : Interface
{
virtual void method()
{
// implementation of Interface::method
}
};
struct A : B
{
};
if B::method is abstract you cannot call it because is not implemented... has no code.
An example:
class A
{
public:
virtual void method1( ) = 0;
virtual void method2( ){ }
};
class B : public A
{
public:
virtual void method1( ) override
{ return A::method1( ); } // Error. A::method1 is abstract
virtual method2( ) override
{ return A::method2( ); } // OK. A::method2 is an implemented method
}
Even if there were a way to do what you want, in the name of the readability of your code, I would not recommend that.
If you do not put the "B::" before "method" call, when I read that, I would say it is a recursive call.
Can I somehow use Curiously Recurring Template Pattern (CRTP) with array?
What I want? I want array of classes that have some foo function. And call it for all objects in array. Like so:
template<class Derived>
struct Base{
void call(){
static_cast<Derived*>(this)->call();
}
};
struct A : Base<A>{
void call(){
cout <<"A";
}
};
struct B : Base<B>{
void call(){
cout <<"B";
}
};
...
Base array[2] = {A(), B()}; // <-- here is my array
array[0].call();
array[1].call();
P.S. I read, also, about AutoList pattern. But it seems it have nothing to do with my problem.
You can't have an array
Base array[2];
since Base is not a class.
Base<A> and Base<B> are classes but the two are completely different classes, with no relationship between them.
Update
You could use something like what #yzt suggested but then that is hardly any more elegant than:
struct Base {
virtual void call () = 0;
};
struct A : Base {
void call () {
cout << "A";
}
};
struct B : Base {
void call () {
cout << "B";
}
};
Base* a [] = {new A(), new B()};
a[0]->call ();
a[1]->call ();
The CRTP class doesn't need to be present at all.
You can use another (non-templated) base and a virtual call, like this:
struct VirtualBase {
virtual void call () = 0;
};
template <class Derived>
struct Base : VirtualBase {
virtual void call () override {
static_cast<Derived*>(this)->real_call ();
}
};
struct A : Base<A> {
void real_call () {
cout << "A";
}
};
struct B : Base<B> {
void real_call () {
cout << "B";
}
};
And use it like this:
VirtualBase * a [] = {new A(), new B()};
a[0]->call ();
a[1]->call ();
Note that to have polymorphism, you need to work with pointers or references (which is one of the problems with your code, because you are trying to put instances themselves into an array.)
Also, note the name change between call and real_call.
And don't forget to delete the instances; for example like this:
for (auto e : a) delete e;
or you can use std::unique_ptr<>, but the initialization of the array will be more verbose.
Update about virtual calls, in response to comments:
If you want to be able to dispatch to different methods determined at runtime, then you have to to use some kind of indirection. You won't be able to let the compiler bake in the call addresses at compile time (which is what happens with ordinary function calls and non-virtual method calls.)
One form of that indirection is using virtual methods; others are using function pointers, or even switch statements. There are other more exotic and less-used forms of call indirection too (e.g. runtime in-memory patching of addresses, etc.) but they are rarely worth the effort.
In short, if you want to have the flexibility of runtime dispatch, you'll have to pay the price.
Update with another sample:
In response to comments on other answers, here's a small sample of CRTP used in conjunction with polymorphism. It's just an example, and not a good one, but I see no reason why they can't be used together.
I have a class (class A) that is designed to be inherited by other classes written by other people.
I also have another class (class B), that also inherits from A.
B has to access some A's member functions that shouldn't be accessed by other inheriting classes.
So, these A's member functions should be public for B, but private for others.
How can I solve it without using 'friend' directive?
Thank you.
EDIT: Example why I need it.
class A
{
public:
void PublicFunc()
{
PrivateFunc();
// and other code
}
private:
virtual void PrivateFunc();
};
class B : public class A
{
private:
virtual void PrivateFunc()
{
//do something and call A's PrivateFunc
A::PrivateFunc(); // Can't, it's private!
}
};
You can't. That's what friend is for.
An alternative would be to change the design/architecture of your program. But for hints on this I'd need some more context.
What you say is: there are two sets of subclasses of A. One set should have access, the other set shouldn't. It feels wrong to have only one brand of subclasses (i.e. B) 'see' A's members.
If what you mean is: only we can use this part of functionality, while our clients can't, there are other resorts.
(Functionality reuse by inheritance often corners you with this kind of problems. If you go towards reuse by aggregation, you may get around it.)
A suggestion:
// separate the 'invisible' from the 'visible'.
class A_private_part {
protected:
int inherited_content();
public:
int public_interface();
};
class B_internal : public A_private_part {
};
class A_export : private A_private_part {
public:
int public_interface() { A_private_part::public_interface(); }
};
// client code
class ClientClass : public A_export {
};
But better would be to go the aggregation way, and split the current "A" into a visible and an invisible part:
class InvisibleFunctionality {
};
class VisibleFunctionality {
};
class B {
InvisibleFunctionality m_Invisible;
VisibleFunctionality m_Visible;
};
// client code uses VisibleFunctionality only
class ClientClass {
VisibleFunctionality m_Visible;
};
Well - if you want exactly what you've described, then friend is the best solution. Every coding standard recommends not using friend but where the alternative design is more complex - then maybe it's worth making an exception.
To solve the problem without friend will require a different architecture
One solution might be to use a form of the pImpl idiom where 'B' derives from the inner implementation object, while the other clients derive from the outer class.
Another might be to place an extra layer of inheritance between 'A' and the "other clients". Something like:
class A {
public:
void foo ();
void bar ();
};
class B : public A { // OK access to both 'foo' and 'bar'
};
class ARestricted : private A {
public:
inline void foo () { A::foo (); }; // Forwards 'foo' only
};
However, this solution still has it's problems. 'ARestricted' cannot convert to an 'A' so this would need to be solved by some other "getter" for 'A'. However, you could name this function in such a way as it cannot be called accidentally:
inline A & get_base_type_A_for_interface_usage_only () { return *this; }
After trying to think of other solutions, and assuming that your hierarchy needs to be as you describe, I recommend you just use friend!
EDIT: So xtofl suggested renaming the types 'A' to 'AInternal' and 'ARestricted' to 'A'.
That works, except I noticed that 'B' would no longer be an 'A'. However, AInternal could be inherited virtually - and then 'B' could derive from both 'AInternal' and 'A'!
class AInternal {
public:
void foo ();
void bar ();
};
class A : private virtual AInternal {
public:
inline void foo () { A::foo (); }; // Forwards 'foo' only
};
// OK access to both 'foo' and 'bar' via AInternal
class B : public virtual AInternal, public A {
public:
void useMembers ()
{
AInternal::foo ();
AInternal::bar ();
}
};
void func (A const &);
int main ()
{
A a;
func (a);
B b;
func (b);
}
Of course now you have virtual bases and multiple inheritance! Hmmm....now, is that better or worse than a single friend declaration?
I think you have a bigger problem here. Your design doesn't seem sound.
1) I think the 'friend' construct is problematic to begin with
2) if 'friend' isn't what you want, you need to re-examine your design.
I think you either need to do something that just gets the job done, using 'friend' or develop a more robust architecture. Take a look at some design patterns, I'm sure you'll find something useful.
EDIT:
After seeing your sample code, you definitely need to re-arch. Class A may not be under your control, so that's a little tricky, but maybe want you want to re-do Class B to be a "has-a" class instead of an "is-a" class.
public Class B
{
B()
{
}
void someFunc()
{
A a; //the private functions is now called and a will be deleted when it goes out of scope
}
};
I find this a interesting challenge. Here is how I would solve the problem:
class AProtectedInterface
{
public:
int m_pi1;
};
class B;
class A : private AProtectedInterface
{
public:
void GetAProtectedInterface(B& b_class);
int m_p1;
};
class B : public A
{
public:
B();
void SetAProtectedInterface(::AProtectedInterface& interface);
private:
::AProtectedInterface* m_AProtectedInterface;
};
class C : public A
{
public:
C();
};
C::C()
{
m_p1 = 0;
// m_pi1 = 0; // not accessible error
}
B::B()
{
GetAProtectedInterface(*this);
// use m_AProtectedInterface to get to restricted areas of A
m_p1 = 0;
m_AProtectedInterface->m_pi1 = 0;
}
void A::GetAProtectedInterface(B& b_class)
{
b_class.SetAProtectedInterface(*this);
}
void B::SetAProtectedInterface(::AProtectedInterface& interface)
{
m_AProtectedInterface = &interface;
}
If you where going to use this sort of pattern all the time, you could reduce the code by using templates.
template<class T, class I>
class ProtectedInterfaceAccess : public I
{
public:
void SetProtectedInterface(T& protected_interface)
{
m_ProtectedInterface = &protected_interface;
}
protected:
T& GetProtectedInterface()
{
return *m_ProtectedInterface;
}
private:
T* m_ProtectedInterface;
};
template<class T, class I>
class ProtectedInterface : private T
{
public:
void SetupProtectedInterface(I& access_class)
{
access_class.SetProtectedInterface(*this);
}
};
class Bt;
class At : public ProtectedInterface <::AProtectedInterface, Bt>
{
public:
int m_p1;
};
class Bt : public ProtectedInterfaceAccess<::AProtectedInterface, At>
{
public:
Bt();
};
class Ct : public At
{
public:
Ct();
};
Ct::Ct()
{
m_p1 = 0;
// m_pi1 = 0; // not accessible error
}
Bt::Bt()
{
SetupProtectedInterface(*this);
m_p1 = 0;
GetProtectedInterface().m_pi1 = 0;
}
If I understand:
A will be subclassed by other developers.
B will be subclassed by other developers and inherits from A.
A has some methods you don't want accessible to outside developers through B.
I don't think this can be done without using friend. There is no way I know of to make members of a superclass available only to direct inheritors.