I have a class tree as such:
class A;
class B : public A;
I then want to create a class which is derived from class B. But I want that derivation to be hidden from outside members as well as anyone else that inherits from class C
class C : private B;
void test() {
C c;
B *b = &c; // compiler error: B in C is private and is therefore not type compatible. This is desired.
}
However, I also want to reveal the inheritance of class A. Hiding class B in this case also hides class A.
void test2() {
C c;
A *a = &c; // Compiler error: A is only accessible through B which is not possible with a private inheritance of B. This is not desired; this conversion should be possible.
}
I could inherit from A again, but that would obviously create duplicate member variables if A has any. I could create a virtual inheritance of class A, however I don't feel it would have the exact effect I desire since that would affect the entire tree rather than this segment (right?)
I suppose the obvious solution would be to create a typecasting member function:
class C : private B {
A * turn_into_A() {
// Since B is an A and we are still in the scope of C, this will succeed
return this;
}
};
However, I'd prefer to avoid explicit typecasts such as that case,
Any sane person might tell me I'm doing this wrong. They'd probably be right. But I would like to know simply for knowledge's sake: is there a way to do this without virtual inheritance or an explicit member function's typecast?
I found a workable solution:
class A {
public:
void somethingA() {
std::cout << "a" << std::endl;
return;
}
};
class B :
public A {
public:
void somethingB() {
std::cout << "b" << std::endl;
return;
}
};
class C :
private B {
public:
using B::A; // While B is private (and hidden), this exposes access to B::A
void somethingC() {
std::cout << "c" << std::endl;
return;
}
};
int main(int argc, char **argv) {
C c;
B* b = &c; // Compiler error: cannot convert because B is private (desired)
A* a = &c; // Okay! (required)
c.somethingC();
c.somethingB(); // Compiler error: private. (desired)
c.somethingA(); // Compiler error: A is exposed, but not A's members. This can be solved by adding 'using B::A::somethingA()' in class declaration (undesired but acceptable in my situation)
a->somethingA(); // Okay! (of course)
}
It's not perfect in that it only exposes C to be able to be converted to A (which for my purposes is what I'll end up doing anyway, so that's fine). However it doesn't directly expose the members of A to allow C to be used as-an-A, eg you cannot call c::somethingA() unless you specifically also expose B::A::somethingA.
Inheritance depicts a IS-A relationship. So, in your object model, B IS-A A, C IS-A B. So, why don't you use
class C : public B { ...};
So that you may view a C object as a B object as well as an A object as need be. Hope that helps.
Related
I try to have an abstract base class act like an interface and instantiate a derived class based on user input. I tried to implement it like this
class A
{
public:
virtual void print() = 0;
};
class B : A
{
public:
void print() override { cout << "foo"; }
};
class C : A
{
public:
void print() override { cout << "bar"; }
};
int main()
{
bool q = getUserInput();
A a = q ? B() : C();
a.print();
}
But that does not work. I’m coming from c# and that would be valid c# so I’m looking for an equivalent way of implement it in c++. Could someone please give me a hint? Thanks!
There are two problems with the code in its current state.
By default in C++, a class that inherits from a class or struct will be private inheritance. E.g. when you say class B : A, it's the same as writing class B : private A -- which in C++ restricts the visibility of this relationship only to B and A.
This is important because it means that you simply cannot upcast to an A from outside the context of these classes.
You are trying to upcast an object rather than a pointer or reference to an object. This fundamentally cannot work with abstract classes and will yield a compile-error even if the code was well formed.
If the base class weren't abstract, then this would succeed -- but would perform object slicing which prevents the virtual dispatch that you would expect (e.g. it won't behave polymorphically, and any data from the derived class is not present in the base class).
To fix this, you need to change the inheritance to explicitly be public, and you should be using either pointers or references for the dynamic dispatch. For example:
class A
{
public:
virtual void print() = 0;
};
class B : public A
// ^~~~~~
{
public:
void print() override { cout << "foo"; }
};
class C : public A
// ^~~~~~
{
public:
void print() override { cout << "bar"; }
};
To model something closer to the likes of C#, you will want to construct a new object. With the change above to public, it should be possible to use std::unique_ptr (for unique ownership) or std::shared_ptr (for shared ownership).
After this, you can simply do:
int main() {
auto a = std::unique_ptr<A>{nullptr};
auto q = getUserInput();
if (q) { // Note: ternary doesn't work here
a = std::make_unique<B>();
} else {
a = std::make_unique<C>();
}
}
However, note that when owning pointers from an abstract base class, you will always want to have a virtual destructor -- otherwise you may incur a memory leak:
class A {
public:
...
virtual ~A() = default;
};
You can also do something similar with references if you don't want to use heap memory -- at which point the semantics will change a little bit.
References in C++ can only refer to an object that already has a lifetime (e.g. has been constructed), and can't refer to a temporary. This means that you'd have to have instances of B and C to choose from, such as:
int main() {
auto b = B{};
auto c = C{};
bool q = getUserInput();
A& a = q ? b : c;
a.print(); // A& references either 'b' or 'c'
}
You need to use pointers :
A* a = q ? static_cast<A*>(new B) : new C;
...
delete a;
A ternary is also a special case here, as it takes the type of the first expression.
If C inherited from B here it would not be a problem.
I have the following class
class A {
private:
B b;
public:
A();
}
class B {
public:
void foo();
void bar();
void foz();
........
}
B has a lot of methods. Sometimes is needed for a "customer" of class A to use method of class B. I could return a reference of B, but in this case I should return a const reference because returning a non-const reference of a private object is not good programming. If the reference is const, foo, bar and so on can't be called because they aren't const. So the only "clean" way seems to recreate the same interfaces in A using delegation to B. But this approach is not really good because I should recreate all the interfaces in A. As alternative I could set B as public in A, but it seems "strange" to me. What should I do in this case?
That is mainly an encapsulation question, and what you want to advertise in the public interface of class A.
If class B is also a public class - read can normally be used by users of class A and not a class internal to a library or framework - and if you want the existence of a B subobject to exist in the public documentation of class A and if you want to allow any operation on the B object, you can safely provide a getter.
If any of the above conditions is false, then the getter would break encapsulation and you would better define delegating methods in class A.
Depending on the general design, it could make sense to declare an interface class (say C) with only the methods that you want to allow from class A, and have B a subclass from C. Then you could safely declare a getter returning a reference on a C object:
class C {
public:
void foo(); // optionally virtual or pure virtual...
void bar();
void foz();
};
class B: public C {
.... // other members not relevant for what is public for A users
};
class A {
private:
B b;
public:
A();
C& getB() {
return b;
}
};
Solution 1. You create a getb() and return reference to B. Its not bad programming in you case particularly.
Solution 2. Create interface function for each corresponding function of b and call them.
void A::foo()
{
b.foo();
}
You can make the data member protectedinstead of private. Documentation says that protected members are not as private as private members, which are accessible only to members of the class in which they are declared, but they are not as public as public members, which are accessible in any function. protectedmembers (be they data members of method members) serve the role you're looking for : they are not accessible from everywhere (safe coding practices), but you can still manage them in clean ways when it makes sense :
If class A has an attribute of type B, is has access to B's
protected and publicmembers
friendfunctions can access both protected and publicmembers of a class they are friend with.
When preceding the name of a base class, the protected keyword specifies that the public and protected members of the base class are protected members of its derived classes.
Here, you're interested by the first item of the list : you can access B' methods from A; BUT B has still safeguards.
When I run the following code (adapted from your code) :
#include <iostream>
using std::cout;
using std::endl;
class B {
public:
void foo() { cout << "foo" << endl; };
void bar() { cout << "bar" << endl; };
void foz() { cout << "foz" << endl; };
};
class A {
protected: // <===== THIS IS THE SIGNIFICANT BIT
B b;
public:
A() {
b.foo();
b.bar();
b.foz();
cout << "A constructor" << endl;
};
};
int main(int argc, char** argv) {
A myA;
return 0;
}
I get the following console output :
foo
bar
foz
A constructor
Which shows that I can access B's methods from A.
i've stumbled upon this problem while doing multi-base inheritance project for my college work. Example of my problem, and code itself: I'm setting up 3 classes, A, B and C.
B inherits publicly from A.
C inherits publicly from B.
I want to set a method publicly in B, that does take as argument a pointer to an object of class A. However it should be able to use only class A objects, neither B or C.
Problem is that Visual Studio 2013 doesn't show any error, and simply allows for my method to be used by B class object on a C class object, which is exactly the opposite of what i want to achieve. Why is that happening?
Does that mean that inheriting somewhat makes C object being interpreted as of type A, B and C at the same time? If not, is there a direct way to bind a method to be used only on classes that it inherits from (c methods on both A and B objects)? Feel free to correct me if i'm wrong anywhere, i'm still a newbie at programing. Thank you for your help! `
class A
{
private:
int x;
string z;
public:
void SetZ()
{
cout << "Set Z: ";
cin >> z;
}
string GetZ()
{
return this->z;
}
};
class B
:public A
{
public:
void use_base(A* k)
{
cout << "here and now, i'm using " << k->GetZ() << " however i, " << this->GetZ() << ", might want to!";
}
};
class C
:public B
{
void use_base(A* k)
{
cout << "extra";
}
};
int main()
{
A Bob;
B Mark;
Bob.SetZ();
Mark.SetZ();
C Karl;
Mark.use_base(&Karl); // doesn't show any error
return 0;
}`
If B inherits publicly from A, then B* can be implicitly converted to A* so a function that takes A* can be called with B* arguments. To prevent this, you could make the inheritance protected or private. However, that might create other problems.
To prevent accidentally passing a B*, you can declare another overload that takes B* and delete it. This overload will win for B* and C* arguments and cause a compilation error. You can also generalize this approach using templates, and so prevent passing a pointer to any class derived from A, without naming all such classes.
void use_base(A* k) { /* do something */ }
void use_base(B*) = delete;
However, that doesn't stop someone from explicitly casting a B* or C* to A* and calling the A* overload.
I have a somewhat basic question on inheritance that i can seem to figure out, I've done a search and not found what I was looking for so I thought I'd ask here (not sure if title of what I'm looking for is correct).
To keep things simple I've made a bit of example code to illustrate what I'm not getting.
Basically if I have a parent class A and two child classes B & C,
where A contains common stuff (say an id with get/set),
while B & C have functions that are class specific.
If you declare a class B like: A *bObject = new B();
how do you then access the class specific functionbObj->specific()`?
I've tried virtual but that requires both B & C to have the same function name / prototype declared.
I've also tried declaring the abstract in A, but that requires it to be prototype to be in A.
Where am i going wrong here? any help on this, probably basic issue would be helpful.
#include <iostream>
using namespace std;
// A class dec
class A
{
public:
A(void);
~A(void);
char id;
void setId(char id);
char getId();
};
// B class dec - child of A
class B :
public A
{
public:
B(void);
~B(void);
void sayHello();
};
//C class dec - child of A
class C :
public A
{
public:
C(void);
~C(void);
void sayGoodby();
};
//a stuff
A::A(void)
{
}
A::~A(void)
{
}
void A::setId(char id)
{
this->id = id;
}
char A::getId()
{
return this->id;
}
//b stuff
B::B(void)
{
this->setId('b');
}
B::~B(void)
{
}
// c stuff
C::C(void)
{
this->setId('c');
}
C::~C(void)
{
}
void C::sayGoodby()
{
std::cout << "Im Only In C" << std::endl;
}
// main
void main ()
{
A *bobj = new B();
A* cobj = new C();
std::cout << "im class: " << bobj->getId() << endl;
bobj->sayHello(); // A has no member sayHello
std::cout << "im class: " << cobj->getId() << endl;
cobj->sayGoodby(); // A has no member sayGoodby
system("PAUSE");
}
Thank you for your time!
To access methods unique to a derived class, you need to cast the base class pointer to the correct derived class type first (a downcast):
A *bobj = new B();
bobj->sayHello(); // compile error
dynamic_cast<B*>(bobj)->sayHello(); // works
dynamic_cast<C*>(bobj)->sayGoodbye(); // run-time error - probably crashes with a segfault/access violation.
dynamic_cast ensures run-time type safety but adds a small overhead to the cast; for pointer casts, it returns a null pointer if the pointed-to object is not actually a B, and you should check the return value before using it. Alternatively, if you are really sure that the pointer you are casting is pointing to the correct object, you can use static_cast which saves you the cost of the run-time checking, but if the pointer is not pointing to the right object, you get undefined behavior.
A *bobj = new B();
A* cobj = new C();
Here instance of B and C is pointed by pointer of A. Since A have no virtual function for B and C's member function sayHello() and sayGoodbye(), they could not called by bobj->sayHello() and cobj->sayGoodbye(). It is not what polymorphism should be do.
Class A should be:
class A
{
public:
A(void);
~A(void);
char id;
void setId(char id);
char getId();
virtual void sayHello(){/* to do */ };
virtual void sayGoodbye(){ /* to do */ };
};
Then the bobj->sayHello(); and cobj->sayGoodbye(); could be called without complaning.
A *bobj = new B();
The static type of bobj is A *. So, at compile time, the compiler looks for the member functions in the class A definition, what ever you tried to access through bobj. Now,
bobj->sayHello();
the compiler will look for the sayHello in class A since the type of bobj is A *. Compiler doesn't care to look into the class B definition to resolve the call. Since the compiler didn't find it sayHello member in A, it is complaining.
However, the dynamic type of bobj is B * and that is a where call is dispatched depending on the dynamic type.
To resolve the issue, you need to virtual functions of the same in class A.
if you really want to call a function like this, you can do like this:
A* bobj = new B();
((B*)bobj)->sayHello();//this can be dangerous if bobj is not an instance of class B
however, the problem here is you do the design wrongly.
basically, if you create an class A, and subclass it to B and C.
And then assign A* bobj = new B(); you are splitting the interfaces and implementations. That means you will use bobj as if it is an instance of class A. and you will not call the functions in B or C. B & C are implementations of interface class A.
it's just like you hire someone to build your house. You give them your blueprint(interfaces) and hire them to build. you can alter the blueprint as you like, they will do whatever in blueprint. but you can't order them directly(just like you can't call the sayHello() directly from bobj).
You can use a down cast via dynamic_cast<>. You can implement a template method in your base class A to facilitate the down cast:
class A
{
public:
A(void);
virtual ~A(void);
char id;
void setId(char id);
char getId();
template <typename CHILD, typename R, typename... ARGS>
R invoke (R (CHILD::*m)(ARGS...), ARGS... args) {
CHILD *child = dynamic_cast<CHILD *>(this);
if (child) return (child->*m)(args...);
std::cout << "down cast error: " << typeid(CHILD).name() << std::endl;
}
};
If that particular instance of A was not the base of CHILD, then dynamic_cast<CHILD *>(this) result in NULL. Note that the virtual destructor in A is required for the dynamic_cast<> to work.
So, you can use it like this:
std::unique_ptr<A> bobj(new B());
std::unique_ptr<A> cobj(new C());
bobj->invoke(&B::sayHello);
bobj->invoke(&C::sayGoodbye);
cobj->invoke(&B::sayHello);
cobj->invoke(&C::sayGoodbye);
Only the first and last invocations are valid. The middle two will cause the "down cast error" message to be printed.
I just cannot imaginate a way to do a call to a function with genericity. I have a code which a have to call a function in two different classes in different moments.
I have A and B classes which I can access one time or other time. Or I access A or I access B. Not both in the same type.
I have code this program but I just cannot imagine how to do this. Or if this is good for performance or codding. I just want to eliminate the C class but I don't know how.
Any idea?
class MyClass
{
public:
MyClass() {} //contructor padrão, não deve ser utilizado isoladamente
virtual int a() = 0;
virtual int b() = 0;
int c()
{
return b();
}
};
class A : public MyClass
{
public:
int a() { return 1; }
int b() { return 1; }
int d() { return 1; }
};
class B : public MyClass
{
public:
int a() { return 1; }
int b() { return 1; }
int e() { return 1; }
};
class C
{
public:
A ca;
B cb;
enum TIPO { A, B };
TIPO Tipo;
C(TIPO tipo) { Tipo = tipo; }
int a()
{
switch(Tipo)
{
case A:
return ca.a();
break;
case B:
return cb.b();
break;
default:
break;
}
}
};
void main()
{
C c(C::B);
c.a();
return;
}
If I understand you correctly, you are trying to eliminate the members (ca,cb), and just call the appropriate base class method.
If that's the case, it can be done by using:
switch(Tipo) {
case A:
return A::a();
case B:
return B::a();
}
However, I would recommend revisiting your design. Typically, situations like this can often be handled by rethinking/reworking the class design so that there is a single base class or interface which defines a(), and instead of creating one concrete class with 2 base classes, create one of two specific, concrete classes derived from a single base class. There is no need for multiple inheritance here. (This is especially true since you know the type at construction time.)
As you've written 'A' and 'B', you don't actually need the C class. By declaring your member functions "virtual" you are using run time polymorphism and this will result in the "correct" functions being called:
void foo (MyClass & mc) {
mc.a ();
}
int main () {
A a;
B b;
foo (a); // 'mc.a()' will call 'A::a'
foo (b); // 'mc.a()' will call 'B::a'
}
Is there some other reason that you need to inherit from C?
First of all, decide if your A and B classes will belong to C by inheritance or by composition. Right now you're doing both, which is both bloating your code and making it confusing.
If you do go for inheritance, then you have another problem: similarly named overridden methods, a prime cause for the Deadly Diamond of Death. Multiple inheritance, in case you haven't heard, is evil. Avoid it unless there is no other way to get the job done.
If you go with composition (my recommendation), then it seems to me that your specification of "not at the same time" becomes unnecessary. You're not accessing the same data, so there's no possibility of a race condition. And if you are (for some ungodly reason) determined to access the same memory space, then you'll need to brush up on multithreading, the implementation of which will differ with each platform you develop on.
Ok, I guess you want C::a() to call A::a() or B::b() depending on what "type" or "mode" C has. First of all there is no need to let C inherit A and B.
class C
{
private:
A ca;
B cb;
enum TIPO { A, B };
TIPO Tipo;
public:
SetTipo(TIPO tipo) { Tipo = tipo; }
// ..
};
void main()
{
C c(C::B); // Start with mode B and call B::b()
c.a();
c.SetTipo(C::A); // Now I'm in mode A .. call A::a()
c.a();
return;
}
This assumes that C really should own one instance of A and one instance of B and I'm not sure if that's what you want. Your question didn't state if that's the case or not.
Cheers
This question is very unclear. I have another interpretation of the question, along with an answer.
Interpretation: given:
class C {
public:
int a();
int b();
};
You want to call either method a() or method b(), selectable at runtime. Solution: member function pointers.
A member function pointer is like a regular C function pointer, except that it applies to a method in a class, and its type signature includes the name of the class it's invoked on. Here's how to use one with the class I've just given:
typedef int (C::*SELECT_FUNC)(void);
This is the declaration of the member function pointer. It is similar to the declaration of a regular C function pointer, with the addition of a class name. Now we can assign it:
SELECT_FUNC ptr = &C::a;
SELECT_FUNC other_ptr = &C::b;
And to call:
C item;
C *item_ptr;
int rv = item.*ptr();
int rv2 = item_ptr->*other_ptr;
This syntax is funky. Think of the "*" as "dereference". We are dereferencing the member function pointer to get a METHOD, at which point we can invoke the method in what is otherwise the normal way.
The cool thing about this is: it doesn't even matter if the methods are virtual or not. You can assign either a virtual method or a non-virtual method to a member function pointer. If you call a method through a function pointer and the method happens to be virtual, then you'll get a true virtual call (i.e. if the function pointer is declared to point to a base class method, but you use a derived class instance for "this", then the derived class method will be called, just as it is for a normal virtual call.)
I would think through your requirements carefully. Your question is not well asked, which leads me to believe that you do not understand yourself what you really want to achieve. Once you understand what you want to achieve, then either a class hierarchy or member function pointers (or both) may be the best choice to solve your problem.