I have two classes with some methods with same name.
Can I create third class that accept reference from ony of the other two and in the constructor to set obj variable to A or B type?
class A
{
public:
A();
void f();
};
class B
{
public:
B();
void f();
};
class C
{
public:
C(B&);
C(A&);
??? obj;
};
Maybe you want a template class:
template <typename T>
class C
{
T& obj;
public:
explicit C(T& t) : obj(t) {}
void f() { obj.f(); }
};
And then:
A a;
B b;
C<A> c1(a);
C<B> c2(b);
c1.f();
c2.f();
C++ is a very flexible language and as such provides multiple options for what you are asking for. Each with their own pros and cons.
The first route that comes to mind is to use polymorphism.
You have two routes to choose from: static or dynamic polymorphism.
The Static Polymorphic Route
To use static polymorphism (also known as compile-time polymorphism) you should make C a template class:
template <typename T> class C
{
public:
C(T&);
T& obj;
}
The Dynamic Polymorphic Route
To use dynamic (also known as run-time polymorphism) you should provide an interface:
class Fer
{
public:
virtual ~Fer() {}
virtual void f() = 0;
}
Which A and B would implement:
class A : public Fer
{
public:
A();
void f() overide;
};
class B : public Fer
{
public:
B();
void f() overide;
};
C would then be like this:
class C
{
public:
C(Fer&);
Fer& obj;
}
The Variant Route
There are various libraries that provide classes that can safely hold arbitrary types.
Some examples of these are:
Boost.Any
Boost.Variant
QVariant from Qt
When using such classes you generally need some means of converting back to the actual type before operating on it.
You can have a base class that defines the required interface.
class Base
{
public:
Base();
virtual void f();
};
And you can have derived classes that implement the interface.
class A : public Base
{
public:
A();
virtual void f();
};
class B : public Base
{
public:
B();
virtual void f();
};
The class C then refers to the Base class and can actually accept objects of A or B type.
class C
{
private:
Base& base;
public:
C(Base& b) : base(b) {}
};
It can be easily used then.
int main()
{
B b;
C c(b);
return 0;
}
Related
I have two derived classes as follows. This is the simplified design version that I have right now.
class A objects are copy-able but they are big. That is why I used reference in the constructor of the derived_1 class.
I used shared_ptr for the class derived_2 in order to make usage of p_a optional. I noticed that I can also use std::optional in the constructor of the class derived_2. By this I can give hint to the user that this argument is indeed optional.
Please take into consideration that this the simplified version and this member p_a is used in all three classes intensively. Also std::shared_ptr<A&> a is not the only argument for the constructor in the real example. I will be thankful if you show me how to use std::optional properly here.
Is it ok to mix std::optional with std::shared_ptr?
class A
{
int m_a;
public:
A(int a) :m_a(a) {};
};
class Base
{
protected:
std::shared_ptr<A> p_a; //Do I need to change type of p_a???
public:
Base() {};
void print()
{
if (p_a)
std::cout << "p_a is allocated\n";
}
void virtual check() = 0;
};
class derived_1 : public Base
{
public:
derived_1(const A& a)
{
p_a = std::make_shared<A>(a);
}
void check() {};
};
class derived_2 : public Base
{
public:
derived_2(std::shared_ptr<A&> a) //can I use std::optional instead??
{
if (a)
p_a = a;
}
void check() {};
};
I have two classes, let's say Base and Derived:
class Base {
public:
virtual ~Base() = 0;
};
class Derived : public Base {};
and a function foo:
auto foo (Derived* d) {
...
}
Is it possible to automatically downcast its argument? So I could do something like this:
Base* b = new Derived();
foo(b);
Basically I would like to write this without explicit casting it before function call.
I read something about conversion operators/constructors but they seem not useful in my case, do you have any other idea?
Edit: Sorry, I oversimplified the question with 2 classes and just a function. But actually I've got a library of 50-ish functions and 3 classes (a superclass and 2 subclasses). This unfortunately makes the easiest and cleanest solutions unsuitable because in my opinion (correct me if I am wrong) they scale bad.
I can think of three possible solutions, depending on your needs. I've replaced raw pointers with unique_ptrs in my examples.
Case 1: You don't need the base type of each derived type to be the same.
Use CRTP to allow the base type to invoke itself as a derived type. Example implementation:
template <typename DerivedType>
class Base {
template <typename F>
auto invoke_as_derived(F&& f) {
return std::forward<F>(f)(static_cast<DerivedType*>(this));
}
};
class Derived : public Base<DerivedType> {};
Usage:
std::unique_ptr<Base<Derived>> b = std::make_unique<Derived>();
b->invoke_as_derived(foo);
Since you mentioned using a list of Base pointers, this probably won't work for you.
Case 2: You need a shared base type but only have one layer in your type hierarchy and no virtual methods.
Use std::variant and std::visit.
class Derived {};
using Base = std::variant<Derived, /* other derived types */>;
auto foo(Derived*) { ... }
class FooCaller {
operator ()(Derived& d) {
return foo(&d);
}
// Overload for each derived type.
}
Usage:
Base b = Derived();
std::visit(FooCaller{}, b);
Case 3: You need a single base type but also want virtual methods and/or additional layers in your type hierarchy.
You might try the visitor pattern. It takes some boilerplate, but it may be the best solution depending on your needs. Sketch of the implementation:
class Visitor; // Forward declare visitor.
class Base
{
public:
virtual void accept(Visitor& v) = 0;
};
class Derived : public Base
{
public:
void accept(Visitor& v) final { v.visit(*this); }
};
struct Visitor
{
virtual void visit(Derived&) = 0;
// One visit method per derived type...
};
struct FooCaller : public Visitor
{
// Store return value of call to foo in a class member.
decltype(foo(new Derived())) return_value;
virtual void visit(Derived& d)
{
return_value = foo(&d);
}
// Override other methods...
};
Usage:
std::unique_ptr<Base> b = std::make_unique<Derived>();
FooCaller foo_caller;
b->accept(foo_caller);
You could write a visitor that takes a function to apply to the element so you don't have to repeat this for all of your many functions. Alternatively, if you can alter the functions themselves, you could replace your functions with visitor types.
Edit: Simplifying the call syntax back down to foo(b)
Define an overload per function overload set to which you want to pass Base objects. Example, using the 3rd technique:
auto foo(Base* b) {
FooCaller foo_caller;
b->accept(foo_caller);
return std::move(foo_caller.return_value);
}
Now foo(b.get()) will delegate to the appropriate overload of foo at run-time.
The usual approach would not be to downcast, but to use virtual functions. I.e. put void foo() inside of the class.
#include<iostream>
class Base {
public:
virtual ~Base() = default;
virtual void foo() { std::cout << "Base foo()\n"; }
};
class Derived : public Base {
public:
void foo() override { std::cout << "Derived foo()\n"; }
};
int main()
{
Base* b = new Derived();
b->foo();
delete b;
}
outputs:
Derived foo()
If you want to make it impossible to call Base::foo(), you can set
class Base {
public:
virtual ~Base() = default;
virtual void foo() = 0;
};
making Base an abstract class.
But if you really want to call foo(b), you can use a (templated) helper function. E.g.:
#include<iostream>
class Base {
public:
virtual ~Base() = default;
virtual void foo() = 0;
};
class Derived : public Base {
public:
void foo() override {
std::cout << "Derived foo()\n";
}
};
template<typename T>
void foo(T* t)
{
t->foo();
}
int main()
{
Base* b = new Derived();
foo(b);
delete b;
}
The code below won't compile:
struct Base
{
std::vector<void(Base::*)(void)> x;
};
struct Derived : public Base
{
void foo() {}
};
// ...
Derived d;
d.x.push_back(&Derived::foo);
Is it possible to refer derived class in template member x? In the example above I specify exactly Base and derived classes cannot push their own member functions into vector x.
Casting is bad since your code have to assume that this will be called only for instance of Derived class. This means that you either have to assume that all items in x are instance of Derived (in such case declaration of x is to general and should be changed to std::vector<void(Derived::*)(void)> x;) or you have to maintain extra information what which class method is stored in specific position of x. Both approaches are bad.
In modern C++ it is much better do do it like this:
struct Base
{
std::vector<std::function<void()>> x;
};
struct Derived : public Base
{
void foo() {}
};
// ...
Derived d;
d.x.push_back([&d](){ d.foo(); });
Another good approach can be CRTP:
template<class T>
struct Base
{
std::vector<void(T::*)(void)> x;
};
struct Derived : public Base<Derived>
{
void foo() {}
};
// ...
Derived d;
d.x.push_back(&Derived::foo);
You may, but there is no implicit conversion; it requires a cast.
Derived d;
d.x.push_back(static_cast<void(Base::*)()>(&Derived::foo));
The caveat is the if you use that pointer to member with an object that isn't really a Derived, the behavior is undefined. Tread carefully.
As an addendum, if you want to get rid of the cast when taking the pointer, you can do that by encapsulating the push (with some static type checking to boot):
struct Base
{
std::vector<void(Base::*)(void)> x;
template<class D>
auto push_member(void (D::* p)()) ->
std::enable_if_t<std::is_base_of<Base, D>::value> {
x.push_back(static_cast<void(Base::*)()>(p));
}
};
I think I would express this by calling through a non-virtual member function on the base.
example:
#include <vector>
struct Base
{
std::vector<void(Base::*)(void)> x;
// public non-virtual interface
void perform_foo()
{
foo();
}
private:
// private virtual interface for the implementation
virtual void foo() = 0;
};
struct Derived : public Base
{
private:
// override private virtual interface
void foo() override {}
};
// ...
int main()
{
Derived d;
d.x.push_back(&Base::perform_foo);
auto call_them = [](Base& b)
{
for (auto&& item : b.x)
{
(b.*item)();
}
};
call_them(d);
}
Long story short, what I want here is to declare a templated type in a base class and be able to access that type A<T> such that the base class B contains it and the derived class C is able to access it as C::A<T>. I did try declaring an int inside of class B and that can be accessed from the derived C class as C::int, here's the error!
||In constructor ‘D::D()’:|
|74|error: no match for ‘operator=’ (operand types are ‘A<C*>’ and ‘A<B*>’)|
|4|note: candidate: A<C*>& A<C*>::operator=(const A<C*>&)|
|4|note: no known conversion for argument 1 from ‘A<B*>’ to ‘const A<C*>&’|
And this is the code that does compile ( comment A<B*> i; and uncomment A<C*> i; to get the error).
#include <iostream>
//class with a template parameter
template <class a>
class A
{
private:
int somevalue;
public:
A(){}
~A(){}
void print()
{
std::cout<<somevalue<<std::endl;
}
};
//1. could forward declare
class C;
class B
{
protected:
A<B*> i;
//2. and then use
//A<C*> i;
public:
B(){}
~B(){}
A<B*> get()
{
return i;
}
/*
//3. use this return instead
A<C*> get()
{
return i;
}
*/
};
//specialization of B that uses B's methods variables
class C : public B
{
protected:
public:
C(){}
virtual ~C(){}
void method()
{
B::i.print();
}
};
//class D that inherits the specialization of C
class D : public C
{
private:
A<B*> i;//works
//4. but I want the inherited type to work like
//A<C*> i;// so that the type C* is interpreted as B*
public:
D()
{
this->i = C::i;
}
~D(){}
};
///////////////////////////////////////////////////////////////////////
int main()
{
D* d = new D();
delete d;
return 0;
}
But okay what if we tried this std::list<template parameter> LIST and then plug that in? That's the problem A<T> is std::list.
As far as I understand your issue now you seem to have a std::list<Base *> (renamed B to Base for clarity) and want to fill an std::list<Concrete*> (renamed C to Concrete, it's derived from Base) with it.
For that you need to iterate over the Base* pointers, checking for each whether it can be downcast to a Concrete* and if so adding it to the std::list<Concrete*>. You need to think about what to do if the downcast fails, too.
For all of this to work your Base needs to be a polymorphic base class, that is it must contain a virtual member function (don't forget to make the destructor virtual). Also note that this sounds like a catastrophe waiting to happen in terms of managing ownership of those pointers.
template<typename Base, typename Concrete>
std::list<Concrete*> downcast_list (std::list<Base*> const & bases) {
std::list<Concrete*> result;
for (auto const base_ptr : bases) {
Concrete * concrete_ptr = dynamic_cast<Concrete*>(base_ptr);
if (concrete_ptr != nullptr) {
result.push_back(concrete_ptr);
} else {
// Error or ignore?
}
}
return result;
}
Note: a more idiomatic version of this would use iterators.
I found the pattern to my problem, it's actually really simple and it serves as the base for encapsulating a class type a (which is a template parameter to be passed around, try looking at my question as a reference to class a). The pattern is shown below, it's generally what I wanted. I found it on this webpage Using Inheritance Between Templates chapter 7.5 from the book entitled OBJECT-ORIENTED
SOFTWARE DESIGN
and CONSTRUCTION
with C++ by Dennis Kafura. I'll copy it below the edited code for the sake of future reference in case anyone else needs it.
template <class a>
class B
{
private:
public:
B();
~B();
};
template <class a>
class C : public B<a>
{
public:
C();
~C();
};
This is the code it was adapted from.
template <class QueueItem> class Queue
{
private:
QueueItem buffer[100];
int head, tail, count;
public:
Queue();
void Insert(QueueItem item);
QueueItem Remove();
~Queue();
};
template <class QueueItem> class InspectableQueue : public Queue<QueueItem>
{
public:
InspectableQueue();
QueueItem Inspect(); // return without removing the first element
~InspectableQueue();
};
Try changing this:
#include <iostream>
//class with a template parameter
template <class a>
class A {
private:
int somevalue;
public:
A(){}
~A(){}
void print() {
std::cout<<somevalue<<std::endl;
}
};
//1. could forward declare
class C;
class B {
protected:
A<B*> i;
//2. and then use
//A<C*> i;
public:
B(){}
~B(){}
A<B*> get() {
return i;
}
/*/3. use this return instead
A<C*> get() {
return i;
} */
};
//specialization of B that uses B's methods variables
class C : public B {
protected:
public:
C(){}
virtual ~C(){}
void method() {
B::i.print();
}
};
//class D that inherits the specialization of C
class D : public C {
private:
A<B*> i;//works
//4. but I want the inherited type to work like
//A<C*> i;// so that the type C* is interpreted as B*
public:
D() {
this->i = C::i;
}
~D(){}
};
int main() {
D* d = new D();
delete d;
return 0;
}
To Something Like This:
#include <iostream>
//class with a template parameter
template <typename T>
class Foo {
private:
T value_;
public:
Foo(){} // Default
Foo( T value ) : value_(value) {}
~Foo(){}
void print() {
std::cout<< value_ << std::endl;
}
};
class Derived;
class Base {
protected:
Foo<Base*> foo_;
Base(){} // Default;
virtual ~Base(){}
// Overload This Function
template<typename T = Base>
/*virtual*/ Foo<T*> get();
/*virtual*/ Foo<Base*> get() { return this->foo_; }
/*virtual*/ Foo<Derived*> get();
};
class Derived : Base {
public:
Derived() {}
virtual ~Derived() {}
void func() {
Base::foo_.print();
}
void Foo<Derived*> get() override { return this->foo_; }
};
And this is as about as far as I could get trying to answering your question...
There are objects that you are not using in your code
There are methods that aren't being called.
It is kind of hard to understand the direction/indirection
of what you mean to do with the inheritance tree.
You are inheriting from a base class without a virtual destructor
And probably a few other things that I can not think of off the top of my head right now.
I'd be more than willing to try and help you out; but this is as far as I can go with what you currently are showing.
EDIT -- I made changes to the base & derived classes and removed the virtual keyword to the overloaded function template declarations - definitions belonging to those classes.
Here is a skeleton code:
class C{
callMe(){}
};
class A{
// How to use callMe()
};
class B : C {
callMe();
A a;
};
In this example class B extends class C, so it can call callMe() method. But I need to use callMe() using class A given that class A can not extend class C. I wonder how?
you need to make A contain an object of type C.
class A
{
private:
C objC;
public:
void WhateverMethod() { objC.CallMe(); }
};
Also, the syntax for inheritance is
class B : C{
};
If you want B to simply have access to CallMe(), then you do not need to redefine it in B. It will inherit it from C. If you want B to override CallMe then you need to do this:
class C
{
public:
virtual void CallMe() { //definition }
};
class B : public C
{
public:
void CallMe() { //redefine it here }
};
Note, I assume from your syntax errors that you are a JAVA programmer. Methods are not automatically marked as virtual in C++, you have to mark them as virtual if you want to use polymorphism, and you have to use them from a pointer for it to work.
class C{
callMe(){}
friend class A;
};
class A{
//use call me here
};
You need to provide an instance of C:
class C {
public: // has to be public
void callMe() const {}
};
class A{
public:
A(const C& inst) : inst(inst) {}
void foo() {
inst.callMe();
}
private:
const C& inst;
};