I'm not sure if the following code is going to do what I expect it to:
struct Foo
{
// Some variables
};
struct Bar : public Foo
{
// Some more variables
};
struct Baz : public Foo
{
// Some more variables
};
class ExampleBase
{
Foo* A;
int B;
double C;
};
class ExampleBar : public ExampleBase
{
Bar* A;
}
class ExampleBaz : public ExampleBase
{
Baz* A;
}
void DoStuff(ExampleBase& example)
{
// Does things with the Foo*, doesn't need to know what inherited type it is
}
What happens when I have the same name for a pointer (A), which is derived from the same class, but is redefined in the derived Example classes?
I've tried templating the example class like this in order to avoid any ambiguity:
template <typename T>
class ExampleBase
{
T* A;
int B;
double C;
}
And then not deriving any classes from it. When I did this however, I can't get the DoStuff() function to compile. since I want it to accept any of the possible derived types.
Edit: The answers from the possible duplicate explain what happens, but don't solve the issue of a function using the base version
You may want to use a template for to implement DoStuff:
template<typename T>
void DoStuff(ExampleBase<T>& example)
{
// Does things with the T*
}
Alternatively, you can expose both the template and the polymorphic interface separately:
struct ExampleBase
{
int B;
double C;
virtual Foo* getA();
};
template<typename T>
struct ExampleTBase : ExampleBase
{
T* A;
Foo* getA() override { return A; }
};
void DoStuff(ExampleBase& example)
{
// Does things with the getA(), that returns a Foo*
}
Related
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);
}
I have a parent-class with a function. In this function I want to call a template method but the type of the template depends on the type of sub-class. So I want to save the information about T there. I can't call foo with a template because it's from another part of the Program wich i can't change
class A
{
//this will be called on an instance of B or C, A will never be
//instantiated
void foo()
{
ba<T>();
}
}
class B :public A
{
//T want to save here the Type of T so i won't have to call foo() with
//a template
}
class C :public A
{
//here comes another Type for T
}
What you need is a CRTP pattern, which is very common in C++ template programming.
template<class T>
void ba() {}
template<class Derived>
struct A
{
void foo() {
ba<typename Derived::MyT>();
}
};
struct B
: public A<B>
{
using MyT = int;
};
struct C
: public A<C>
{
using MyT = double;
};
int main() {
B b;
b.foo();
C c;
c.foo();
}
You will need to add a template parameter to the base class A and then specify the type in the declaration of B and C. See the example below:
template <typename T>
class A
{
public:
void foo()
{
ba<T>();
}
};
class B : public A<int>
{
};
class C : public A<bool>
{
};
int main()
{
B b;
C c;
b.foo(); // This calls ba<int>()
c.foo(); // This calls ba<bool>()
return 0;
}
It might be good to spend some time reviewing how templates and inheritance work.
Inheritance
Templates
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.
Suppose I have the following class definitions
struct base {
virtual int f() = 0;
};
struct A: public base {
int f() final { return 1; }
};
struct B: public base {
int f() final { return 2; }
};
Is it possible to turn A and B into templates that take a bool parameter that specifies whether to inherit from the base or not? I have usage cases that do or don't require a base class providing a common interface.
Assume that A and B have a lot of member functions, so duplicating implementation would be tedious. But sizeof(A) and sizeof(B) are small.
Sure:
template <bool> struct A
{
// ...
};
template <> struct A<true> : base
{
// ...
};
(Note that you could make A<true> derive from A<false> if that avoids redundancy.)
For example:
template <bool> struct A
{
void f() { std::cout << "A::f called\n"; }
};
template <> struct A<true> : A<false>, base
{
void f() override { A<false>::f(); }
};
int main()
{
A<false> a1;
A<true> a2;
a1.f();
a2.f();
static_cast<base&>(a2).f();
}
I came up with the more direct approach I was looking for, without code duplication.
struct base {
virtual int f() = 0;
};
struct empty_base { };
template <bool Inherit>
struct A final: public std::conditional_t<Inherit,base,empty_base> {
int f() { return 1; }
};
Since you are using a pure base class the distinction shouldn't be important as your optimizer will avoid the virtual function call when you call A::f() since there will never be a derived class that implements a different version of f().
Also you can instead do class A final : base if you don't plan on inheriting from A to avoid having to add final to each function.
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;
}