The following question might look like a duplicate but I couldn't find the exact idea anywhere else in the site.
A brief introduction: This question raised as I was trying to understand a little more complexity inheritance combination in my class.
One note before I present the question - I don't look for a sort of "Solution", only wish to discuss with you about the topic and acquire a better thinking.
Suppose you have the following lines:
class C : public B
{
public :
C (const B& b) : B (b) {}
B& operator*() {return *this;}
};
int main() {
A* pA = new B();
C& c = pA -> doIt();
*c = *pA;
c = *pA;
return 1;
}
This code isn't full and this is the whole purpose - assume it does complie and extract the constraints in this code.
Still I wouldn't just write a code and ask you to explain any constraint of the top off your head but instead I will add my concreate question:
What constraints do we have for the following line :
C& c = pA -> doIt();
As far as I understand, the above code has one staring constraint which is the hierarchy order of these class : C is derived of B and B is dervied of A (correct me If I'm wrong..)
I was trying to actually define these classes while keeping the hierarchy I described above, and I couldn't have doIt() to return a type of its derived class C. I can use incomplete type C& in the prototype of an A function but yet I cannot return an object of type C.
Thank you in advance,
SyndicatorBBB
Try this:
class C;
struct A
{
C & doIt();
};
struct B : A
{
void operator=(A const &) { }
};
class C : public B
{
public :
using B::operator=;
C (const B & b) : B(b) {}
B & operator*() { return *this; }
};
C & A::doIt()
{
static B bimpl;
static C cimpl(bimpl);
return cimpl;
}
Note that the implicit assignment operator hides the base version, so we need explicit unhiding of the operator with the using declaration.
Related
I have a Class A, in the class there is some important member (lets call it someVeryImportantNumber) and also objects of class B. In class B there are objects of class C and so on..., similar to a tree structure (could be 4, 10, or 20 levels of such objects.)
How could i get access to someVeryImportantNumber from the bottom of the hierarchy (to access someVeryImportantNumber from class D).
I was thinking about passing the number down the hierarchy, but this seems not very effective approach when i have lets say 10 or more of levels hierarchy.
Is there some smarter way to do it? I looked at dependency injection but it is not the way to go for me...
Any suggestions? Thank you...
class D {
public:
void foo() {
// need to use someVeryImportantNumber here
}
}
class C {
public:
D d1;
D d2;
D d3;
}
class B {
public:
C c1;
C c2;
}
class A {
public:
int someVeryImportantNumber = 1234;
B b;
}
int main() {
A a;
return 0;
}
You can use a reference to avoid copying that someVeryImportantNumber, and pass it through the constructors:
class D {
const int& someVeryImportantNumber_;
public:
D(const int& someVeryImportantNumber) : someVeryImportantNumber_(someVeryImportantNumber) {}
void foo() {
// need to use someVeryImportantNumber here
}
}
class C {
public:
C(const int& someVeryImportantNumber)
: d1(someVeryImportantNumber), d2(someVeryImportantNumber), d3(someVeryImportantNumber) {}
D d1;
D d2;
D d3;
}
class B {
public:
B(const int& someVeryImportantNumber)
: c1(someVeryImportantNumber), c2(someVeryImportantNumber) {}
C c1;
C c2;
}
class A {
public:
A() : b(someVeryImportantNumber) {}
int someVeryImportantNumber = 1234;
B b;
}
int main() {
A a;
return 0;
}
You cannot do what you're asking.
The reason is simple: in your example, D is contained in C as 3 separate instances, and there is no way to tell, from an object of type D, which instance it belongs to (d1, d2, or d3).
On the other hand, you could access the container instance through something like container_of macro, provided that you also know which instance D belongs to. See https://radek.io/2012/11/10/magical-container_of-macro/. Notice that container_of is used in C but it works in C++ as well.
For instance, if you know that your D is accessed from C::d1, you could use container_of(this, C, d1) to access the instance of C and then reiterate the procedure to access B and then A.
But remember, there is no way to know at run time which one of the 3 instances of D your this pointer refers to, unless you somehow encode the information in your classes.
Suppose I have the class
class A {
protected:
int x,y;
double z,w;
public:
void foo();
void bar();
void baz();
};
defined and used in my code and the code of others. Now, I want to write some library which could very well operate on A's, but it's actually more general, and would be able to operate on:
class B {
protected:
int y;
double z;
public:
void bar();
};
and I do want my library to be general, so I define a B class and that's what its APIs take.
I would like to be able to tell the compiler - not in the definition of A which I no longer control, but elsewhere, probably in the definition of B:
Look, please try to think of B as a superclass of A. Thus, in particular, lay it out in memory so that if I reinterpret an A* as a B*, my code expecting B*s would work. And please then actually accept A* as a B* (and A& as a B& etc.).
In C++ we can do this the other way, i.e. if B is the class we don't control we can perform a "subclass a known class" operation with class A : public B { ... }; and I know C++ doesn't have the opposite mechanism - "superclass a known class A by a new class B". My question is - what's the closest achievable approximation of this mechanism?
Notes:
This is all strictly compile-time, not run-time.
There can be no changes whatsoever to class A. I can only modify the definition of B and code that knows about both A and B. Other people will still use class A, and so will I if I want my code to interact with theirs.
This should preferably be "scalable" to multiple superclasses. So maybe I also have class C { protected: int x; double w; public: void baz(); } which should also behave like a superclass of A.
You can do the following:
class C
{
struct Interface
{
virtual void bar() = 0;
virtual ~Interface(){}
};
template <class T>
struct Interfacer : Interface
{
T t;
Interfacer(T t):t(t){}
void bar() { t.bar(); }
};
std::unique_ptr<Interface> interface;
public:
template <class T>
C(const T & t): interface(new Interfacer<T>(t)){}
void bar() { interface->bar(); }
};
The idea is to use type-erasure (that's the Interface and Interfacer<T> classes) under the covers to allow C to take anything that you can call bar on and then your library will take objects of type C.
I know C++ doesn't have the opposite mechanism - "superclass a known
class"
Oh yes it does:
template <class Superclass>
class Class : public Superclass
{
};
and off you go. All at compile time, needless to say.
If you have a class A that can't be changed and need to slot it into an inheritance structure, then use something on the lines of
template<class Superclass>
class Class : public A, public Superclass
{
};
Note that dynamic_cast will reach A* pointers given Superclass* pointers and vice-versa. Ditto Class* pointers. At this point, you're getting close to Composition, Traits, and Concepts.
Normal templates do this, and the compiler will inform you when you use them incorrectly.
instead of
void BConsumer1(std::vector<B*> bs)
{ std::for_each(bs.begin(), bs.end(), &B::bar); }
void BConsumer2(B& b)
{ b.bar(); }
class BSubclass : public B
{
double xplusz() const { return B::x + B::z; }
}
you write
template<typename Blike>
void BConsumer1(std::vector<Blike*> bs)
{ std::for_each(bs.begin(), bs.end(), &Blike::bar); }
template<typename Blike>
void BConsumer2(Blike& b)
{ b.bar(); }
template<typename Blike>
class BSubclass : public Blike
{
double xplusz() const { return Blike::x + Blike::z; }
}
And you use BConsumer1 & BConsumer2 like
std::vector<A*> as = /* some As */
BConsumer1(as); // deduces to BConsumer1<A>
A a;
BConsumer2(a); // deduces to BConsumer2<A>
std::vector<B*> bs = /* some Bs */
BConsumer1(bs); // deduces to BConsumer1<B>
// etc
And you would have BSubclass<A> and BSubclass<B>, as types that use the B interface to do something.
There is no way to change the behaviour of a class without changing the class. There is indeed no mechanism for adding a parent class after A has already been defined.
I can only modify the definition of B and code that knows about both A and B.
You cannot change A, but you can change the code that uses A. So you could, instead of using A, simply use another class that does inherit from B (let us call it D). I think this is the closest achievable of the desired mechanism.
D can re-use A as a sub-object (possibly as a base) if that is useful.
This should preferably be "scalable" to multiple superclasses.
D can inherit as many super-classes as you need it to.
A demo:
class D : A, public B, public C {
public:
D(const A&);
void foo(){A::foo();}
void bar(){A::bar();}
void baz(){A::baz();}
};
Now D behaves exactly as A would behave if only A had inherited B and C.
Inheriting A publicly would allow getting rid of all the delegation boilerplate:
class D : public A, public B, public C {
public:
D(const A&);
};
However, I think that could have potential to create confusion between code that uses A without knowledge of B and code that uses knows of B (and therefore uses D). The code that uses D can easily deal with A, but not the other way 'round.
Not inheriting A at all but using a member instead would allow you to not copy A to create D, but instead refer to an existing one:
class D : public B, public C {
A& a;
public:
D(const A&);
void foo(){a.foo();}
void bar(){a.bar();}
void baz(){a.baz();}
};
This obviously has potential to mistakes with object lifetimes. That could be solved with shared pointers:
class D : public B, public C {
std::shared_ptr<A> a;
public:
D(const std::shared_ptr<A>&);
void foo(){a->foo();}
void bar(){a->bar();}
void baz(){a->baz();}
};
However, this is presumably only an option if the other code that doesn't know about Bor D also uses shared pointers.
This seems more like static polymorphism rather dynamic. As #ZdeněkJelínek has already mentioned, you could you a template to ensure the proper interface is passed in, all during compile-time.
namespace details_ {
template<class T, class=void>
struct has_bar : std::false_type {};
template<class T>
struct has_bar<T, std::void_t<decltype(std::declval<T>().bar())>> : std::true_type {};
}
template<class T>
constexpr bool has_bar = details_::has_bar<T>::value;
template<class T>
std::enable_if_t<has_bar<T>> use_bar(T *t) { t->bar(); }
template<class T>
std::enable_if_t<!has_bar<T>> use_bar(T *) {
static_assert(false, "Cannot use bar if class does not have a bar member function");
}
This should do what you'd like (i.e. use bar for any class) without having to resort to a vtable lookup and without having the ability to modify classes. This level of indirection should be inlined out with proper optimization flags set. In other words you'll have the runtime efficiency of directly invoking bar.
I have a problem with my code.
class A{
virtual foo()=0;
}
class B: public A {
foo();
foo2();
operator X(A * a) {a->foo2()} //doesn't work
}
class C: public A {
foo();
foo2();
operator X(A * a) {a->foo2()} //doesn't work.
}
So I have a virtual class, and 2 classes that inherit from it. And I have to define an operator X that acts on an A object, no matter if it is B or C (since it can't be A because A is abstract). The problem is that the operator calls foo2(), which I'm not allowed to write in class A. What should I do?
Thanks a lot for helping me. This is my first post.
The right answer is to declare foo2 pure virtual in A. However you have been told you are not allowed to do this. Boo :-(
Your only remaining option is to use dynamic_cast.
void do_foo2(A* a)
{
if (B* b = dynamic_cast<B*>(b))
return b->foo2();
C& c = dynamic_cast<C&>(*a); // Will throw if a is not B or C.
return c.foo2();
}
Then
void B::operator X(A* a)
{
do_foo2(a);
}
Note: This all assumes you are supposed to make B::operator X work with both B and C.
I have the following (simplified) C++ code.
class A
{
};
class B
{
public:
A addSomething(int something)
{
this->something = something;
}
private:
int something;
};
class C : public A
{
};
void main()
{
B variableB = B();
A variableA;
variableA = variableB.addSomething(123);
C variableC;
variableC = variableB.addSomething(456);
}
I have three classes: A, B and C. B is considered as a master or main class while C and A represent subclasses in my context.
Class B has a public method whose type has to be A and adds an integer value to its private property. Class C extends class A.
In the main function the master class is instantiated and its instance is used to add the integer value, which works just fine.
However, doing the same with the instance derived from class A does not work. It returns an error saying:
no operator "=" matches these operands
I am aware that it is caused by the fact that in the master class the addSomething function has the type of class A, but I need it to work with its child classes as well.
Is there a way to get it working without changing class B?
Your goal is to give a A-type-value to a C-type-value, which is not about class B's business. What you need to do is to write a constructor function for class C and give the value to variableC.
So add codes for class C:
class C : public A
{
public:
C() {}
C(A a){}
};
The compiler does not know how to assign an instance of A to a variable of type C.
If you cant change class B, you could implement the operator= in class C:
class C : public A
{
public:
C& operator=(const A& a)
{
// assign A to C
return *this;
}
};
One of the corner stones of OOP is reusing code instead of repeat it over and over. Thus, your projects shorten and get more readable.
C++ gives you all the tools you need to reuse methods instead of repeating the code. Although when it comes to constructors I do not know how to reuse them.
I am not talking of heritage or how to send a message to the father. I am talking about reusing the constructor of the class itself.
The analogy in JAVA is something like this:
public Foo() {
this(0,0,0);//Not needed in this case, just to clarify
}
public Foo(Foo f){
this(f.getA(), f.getB(), f.getC());
}
public Foo(int a, int b, int c) {
this.a = a;
this.b = b;
this.c = c;
}
My question is, is there any syntaxis in C++ that allows you to do so?
C++11 has added constructor delegation and constructor inheritance.
To inherit constructors, a using-declaration is required:
class Base { ... };
class Derived : public Base
{
using Base::Base;
};
To delegate, use the ctor-initializer, but specify another constructor in the same class, instead of any subobjects (all base and member subobjects will be initialized by the constructor delegated to):
class Another : public Base
{
int member;
Another(int x)
: Base(), member(x) // non-delegating constructor initializes sub-objects
{}
Another(void)
: Another(5) // delegates -- other constructor takes care of Base and member
{}
};
And perfect forwarding can also come in handy.
Others already answered about C++11, but for C++03 there's a possible workaround: using a base class with needed constructor(s).
struct foo_base {
foo_base(int a, int b, int c) : a(a), b(b), c(c) { }
int a, b, c;
};
struct foo : foo_base {
foo() : foo_base(0, 0, 0) { }
foo(const foo& other) : foo_base(other.a, other.b, other.c) { }
foo(int a, int b, int c) : foo_base(a, b, c) { }
};
Of course, you need to consider whether it's worth the boilerplate for your purposes.
The generally accepted soultion for current compilers is to do this:
class Bar{
pubilc:
Foo() {
init(0,0,0);
}
Foo(const Foo &f){
init(f.getA(), f.getB(), f.getC());
}
Foo(int a, int b, int c) {
init(a,b,c);
}
private:
void init(int a, int b, int c){
this->a = a;
this->b = b;
this->c = c;
}
};
While this may seem like over kill in this example, that is only because of the simplicity of the example. In a real world application this would actually bring benefits in terms of reduction of repeated code.
OK C++11 covers what you need.
But your simple case has an easy solution:
/* This one is covered by providing default parameters see below.
public Foo() {
this(0,0,0);//Not needed in this case, just to clarify
}
This is done automatically by the compiler.
You do not need to write any code for this:
public Foo(Foo f){
this(f.getA(), f.getB(), f.getC());
}
The compiler generated version actually looks like this:
public Foo(Foo const& f)
: a(f.a)
, b(f.b)
, c(f.c)
{}
*/
// Now you can use all three methods and they work fine:
public Foo(int a = 0, int b = 0, int c = 0)
: a(a)
, b(b)
, c(c)
{}
F f1; // default construct no parameters: uses the three parameter version
F f2(f1); // Copy constructed. Generated by the compiler.
F f3(1,2,3); // Nomal constructor