the member variable with the same name in derived class - c++

UPDATE: the behaviour is not template specific, so
struct Derived : public Base {
OverrideFoo* m_data {new OverrideFoo()};
}
will do the same. so it seems m_data in Derived and m_data in Base both exist in memory layout. If we define a function in Derived,
e.g., Derived::print() { m_data->print()}, this will use m_data in Derived, however, if base function is called on derived object, it still use m_data from Base.
I was surprised with the behaviour of the following code, it prints "from foo", rather than the "from override foo". why is it like this? shouldn't the "m_data" be the type of "OverrideFoo"?
#include <iostream>
using namespace std;
struct Foo {
void print() {
printf("from foo\n");
}
};
struct OverrideFoo {
void print() {
printf("from override foo\n");
}
};
struct Base {
void useData() {
m_data->print();
}
Foo* m_data {new Foo()};
};
template <class t>
struct Derived : public Base {
t* m_data {new t()};
};
int main()
{
Derived<OverrideFoo> d;
d.useData();
return 0;
}

When you call d.useData(), you are calling Base::useData(), which accesses Base::m_data.
I suppose you're expecting Base::useData() to use Derived::m_data, just because the variable has a similar name. However that's not how this works. Both classes get their own independent m_data, and in your case, with different types.
It's true that Derived::m_data hides Base::m_data, which may suggest to you that they are related or that one "overrides" the other. Don't confuse that with hiding. The hiding is a natural consequence of the similar naming. If Derived needs to access Base::m_data, it must qualify it in order to disambiguate from its own m_data.
Note: Member variables / fields cannot be overridden. If you need an override-style behavior, you'll need to do it via a member function (something like virtual IPrintable* GetPrintable(). And the base class must grant the possibility of overriding with the virtual keyword.
Another way to think about this: Base, despite what its name suggests, is a complete type. You can do Base x; to instantiate and use this class, without being derived. The compiler generates code for Base which is complete and functional, including the code to access Base::m_data. If m_data were somehow overrideable, how could this code be generated? What would Base understand sizeof(*m_data) to be, if its datatype could be overridden in some base class? How would the compiler know what m_data even refers to, if you're suggesting it can be changed by any class which derives it?
Another point: If members were able to be overridden by default (without the virtual keyword), it would cause mass chaos for base classes. Imagine writing a generic base class and risking that derived classes could unknowingly change the state of the base? Or imagine writing a derived class and being concerned about your variable naming because "well maybe a base class used the same name?"
So let's summarize the key points:
Fields cannot be overridden, period. It would break sizeof() among lots of other things (whole other topic)
Base classes must explicitly grant derived classes to override member functions via the virtual keyword.
There are probably better ways to do what you're attempting though. The most natural for me would be to specify the Foo type as a template parameter to Base.
Like this:
struct Foo1 {
void print() {
printf("from foo\n");
}
};
struct Foo2 {
void print() {
printf("from override foo\n");
}
};
template<typename TData>
struct Base {
void useData() {
m_data.print();
}
TData m_data;
};
template <typename TData>
struct Derived : public Base<TData> {
};
int main()
{
Derived<Foo1> d1;
d1.useData();
Derived<Foo2> d2;
d2.useData();
return 0;
}
It's hard to know the best approach for you, because this is an unrealistic contrived example.

Try this code out and you will find that the two m_data has different memory address, which means they are different variable.
#include <iostream>
using namespace std;
struct Foo {
void print() {
printf("from foo\n");
}
};
struct OverrideFoo {
void print() {
printf("from override foo\n");
}
};
struct Base {
void useData() {
m_data->print();
std::cout << m_data << std::endl;
}
Foo* m_data {new Foo()};
};
template <class t>
struct Derived : public Base {
t* m_data {new t()};
};
int main()
{
Derived<OverrideFoo> d;
d.useData();
d.m_data->print();
std::cout << d.m_data << std::endl;
return 0;
}

Related

How to send a pointer of an overriden virtual function to the base class?

An example:
class Base
{
protected:
virtual void function() { std::cout << "Base\n"; }
void callfunction(void (Base::* func)()) { (this->*func)(); }
};
class Derived1 : public Base
{
public:
void publicCall() { callfunction(&Derived1::function); }
private:
void function() override { std::cout << "Derived1\n"; }
};
I would like to be able to send the derived function pointer to the base class to fulfill a pattern that can be specified in the base class. Thus, reusing code.
However, I'm not sure what the type is supposed to be in the base class since Base::* is not a Derived1::*.
I get the following error:
No instance of overloaded function callfunction matches the argument list: arguments types are (Derived1::*)
Now obviously, I could change the data type to be Derived1::*, but that wouldn't allow me to send in other derived class virtual functions back to Base to handle, such as Derived2::function()
Can a template sort of function be created like this?
Just send &Base::function. Since it's virtual, the right one will be called.
The only problem here is that Base::function is protected and you cannot access it from Derived (strange but true). OTOH &Derived::function won't convert to void (Base::* func)() (and for a good reason). So you have to either make Base::function public, or provide an accessor:
class Base {
...
protected:
auto getFunction() { return &Base::function; }
Live demo
Use std::function<> instead of C style function pointer.
std::function<returnType (parameterType)> functionPointer = functionName;
Do not forget to include <functional>.
I think this will resolve your problem, but for sure it is preferred.
To pass it directly:
void callfunciton(const std::function<void()>& func);
and call by
callfunction([]{ function(); });
EDIT:
Read this to learn why you should use std::function<>.
You can cast the member function pointer to the base class member function pointer type: callfunction(static_cast<void (Base::*)()>(&Derived1::function));. Full example:
class Base
{
protected:
virtual void function() { std::cout << "Base\n"; }
void callfunction(void (Base::* func)()) { (this->*func)(); }
};
class Derived1 : public Base
{
public:
void publicCall() { callfunction(static_cast<void (Base::*)()>(&Derived1::function)); }
private:
void function() override { std::cout << "Derived1\n"; }
};
This is allowed; see cppreference on pointers to member functions:
Pointer to member function of a base class can be implicitly converted to pointer to the same member function of a derived class ...
Conversion in the opposite direction, from a pointer to member function of a derived class to a pointer to member function of an unambiguous non-virtual base class, is allowed with static_cast and explicit cast
In this case, we are converting derived to base rather than vice-versa, so we need to static_cast.
You can avoid requiring the cast from the call-site by casting in Base from a template:
class Base
{
protected:
virtual void function() { std::cout << "Base\n"; }
void callfunction(void (Base::* func)()) { (this->*func)(); }
template <typename Derived, std::enable_if_t<std::is_convertible_v<Derived const*, Base const*>, int> = 0>
void callfunction(void (Derived::* func)()) { callfunction(static_cast<void (Base::*)()>(func)); }
};
class Derived1 : public Base
{
public:
void publicCall() { callfunction(&Derived1::function); }
private:
void function() override { std::cout << "Derived1\n"; }
};
Compiler Explorer link: https://godbolt.org/z/3x8qPK4Tf
Your question is asking for CRTP, a poorly named but well known label for the idiom described in a 1995 article by Jim Coplien, titled "A Curiously Recurring Template Pattern". The idea is well documented, so I won't go into depth, but the idea is pretty simple: The base class takes a template argument, and the derived class provides its type to the base. Then the base class can "downcast" the this pointer to the derived type and call the function without needing a virtual call.
https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern
What is the curiously recurring template pattern (CRTP)?
I think that a template function should work
template<class _DType>
void Base::callFunction(void(_DType::*func)()) { func(); }
then the function from Derived1
void Derived1::publicCall() { Base::callFunction(&Derived1::function); }
This work as long as Derived1 is derived by Base, that is not what you wrote but I'm assuming you just missed, anyway next time I would add class Derived1: public Base to have a more clear code.

Use static_cast in a class hierarchy to enable visitor pattern

Imagine following scenario. I derive from a library class to enable the visitor pattern:
#include <iostream>
#include <vector>
struct MyClassA;
struct MyClassB;
struct MyVisitor{
virtual void visit(MyClassA* c) { std::cout << "My Class A" << std::endl; }
virtual void visit(MyClassB* c) { std::cout << "My Class B" << std::endl; }
};
struct LibClass {};
struct MyClass : public LibClass {
virtual void Accept(MyVisitor& visitor) = 0;
};
struct MyClassA : public MyClass {
virtual void Accept(MyVisitor& visitor) {
visitor.visit(this);
}
};
struct MyClassB : public MyClass {
virtual void Accept(MyVisitor& visitor) {
visitor.visit(this);
}
};
// vector signature can't be changed
void foo(std::vector<LibClass*>& v) {
MyVisitor visitor;
for(auto libC : v) {
auto myC = static_cast<MyClass*>(libC); // questionable line
//auto myC = dynamic_cast<MyClass*>(libC); // don't want to use dynamic cast
myC->Accept(visitor);
}
}
int main() {
// vector signature can't be changed
std::vector<LibClass*> v;
v.push_back(new MyClassA());
v.push_back(new MyClassB());
foo(v);
return 0;
}
The output is as expected:
My Class A
My Class B
This is a question regarding design. In my eyes, it is bad style to use dynamic_cast and should be avoided. As the vector can get quite large, I also want to avoid calls on the iteration to dynamic_cast.
I can be sure, that every pointer in the vector is derived from MyClass.
I want to use the visitor pattern to implement features depending on the derived class, so I will implement derived classes of MyVisitor, too. MyVisitor later could be provide a virtual interface for all possible childrens. The concrete Visitors than can override only that methods, on which children they want to interact with.
So my questions are:
Is there any danger using the static_cast in that way?
Would you consider this a good design under the circumstance, that I want to insert the possibilty to use the visitor pattern?
dynamic_cast is safer (assuming checking for nullptr) as compiler might check at runtime that the class is really what you want. (No compile-time hierarchy check, due to possible multiple inheritance). foo can be used safely (Even by LibClass which are not MyClass).
With static_cast, you do a promise to the compiler. Breaking it would lead to UB.
The only check done at compile time is that derived class (MyClass) is actually in the hierarchy of the base class (LibClass).
foo signature is now misleading, as you expect only MyClass instead of any LibClass.
But as long as you don't break that promise, code is ok.

C++ access member of templated derived class without typecast

Is it possible to acces a member of a derived class using a pointer to the base class?
// Example program
#include <iostream>
#include <vector>
#include <memory>
#include <string>
class A {
public:
std::string x = "this is the wrong x\n";
};
template <class T>
class B : public A {
public:
T x;
};
int main()
{
std::vector<std::unique_ptr<A>> vector;
auto i = std::make_unique<B<int>>();
i->x = 6;
vector.push_back(std::move(i));
for(auto &element : vector){
std::cout << element->x;
}
}
Here I'm always getting the output from class A. I cannot typecast it because I don't know whether the element is of type A or type B in advance. Is there a proper way to do this?
The proper way would be to make a virtual function to perform the task like printing.
class A {
public:
std::string x = "this is the wrong x\n";
virtual ~A() = default;
virtual void print() const { std::cout << x; }
};
template <class T>
class B : public A {
public:
T x;
virtual void print() const override { std::cout << x; }
};
int main()
{
std::vector<std::unique_ptr<A>> vector;
auto i = std::make_unique<B<int>>();
i->x = 6;
vector.push_back(std::move(i));
for(auto &element : vector){
element->print();
}
}
If you have a pointer to a base class, you can only access things defined on that base class (without typecasting). For all the compiler knows, it is an instance of the base class and has nothing else.
Polymorphic behavior involves using virtual functions - derived classes can change which function is called when invoking a virtual function of the base class. Note that this mechanism does not exist for members (what would you change about a member? There's only the type, and changing that in a derived class makes no sense). So the only meaningful thing you can do with pointers to base classes that should have customized behavior is to call their virtual functions.
Now, you could think "ok, I'll just make access to x go through a virtual function", but the problem here is that you must specify the involved types when you declare the virtual function in the base class already. That makes sense: The compiler needs to know which types a function involves, even a virtual one. You may only pass and return different types in the overriding functions if they are "compatible" - see covariance and contravariance for more information.
So unless all your T are covariant, virtual functions cannot help you either.
The core flaw with your concept is that you want to have some type (i.e. element->x) in a non-templated function depend on the dynamic type of some object (i.e. element). That is impossible because the compiler must know the type of each expression at compile-time. So you must approach your problem differently.

Changing member types in inheritance

Given a base class Base that has two derived classes, DerA and DerB, can the derived classes have a member variable that is used in a Base member function, but is a different type for each class?
class Base {
* a // Declare a as *something*, so it can be used by "doWork"
template <typedef T>
void doWork(T b) { // Add another value to "a" which is of its same type
a += b; // For example; an operation that works on "a", no matter what numeric type it is
}
}
class DerA : public Base {
// Make "a" an int
}
class DerB : public Base {
// Make "a" a float
}
In practice, a will be a base struct, while DerA and DerB will have derived versions of the base struct (derivative classes will each have a derived form of the struct specific to their purpose, but each must do a simple operation on a, so it seems pointless to copy/paste that simple function for each derivative when I can just use a template function). I would just type a as the base struct type, but then I lose access to the various specialized member functions and variables that each derived struct has (if I understand inheritance correctly).
I apologize if this question is a repeat, but I don't know what this quality would be called, so Googling proved fruitless.
What you might want is the CRTP.
template<class D>
struct Base {
D* self() { return static_cast<D*>(this); }
D const* self() const { return static_cast<D*>(this); }
template<class T>
void doWork(T b) {
self()->a += b;
}
};
struct DerA : public Base<DerA> {
int a;
};
struct DerB : public Base<DerB> {
double a;
};
Here we pass the derived type to our base class. Within the base class, you can use self()-> to access fields in the derived type. This allows basically full access to the derived type, while letting us share code in the base class.
Note that you cannot pass DerA and DerB around as a Base this way. If you want that, you need a virtual method doWork, and virtual template methods don't exist.
CRTP stands for the curiously repeating template pattern, which I imagine is named because it is strange, it involves repeating a type, and it keeps on showing up in strange corners as being useful.
Type erasure probably won't work either, as you want to dispatch the type erasure from two different spots in the code base (the double dispatch problem: you need a centralized list of types supported to do the type Cartesian product on).
To expand on that, in order to support a+=b where both a and b are arbitrary types, you would have to expand over all types twice over, including types that are never mutually visible at the same spot in a compilation unit. That isn't possible.
If you need a common base, and there are only some types you pass to doWork, here is how you do it:
struct Base {
virtual void doWork( double ) = 0;
virtual void doWork( int ) = 0;
virtual void doWork( long long ) = 0;
};
template<class D>
struct Base_helper:Base {
D* self() { return static_cast<D*>(this); }
D const* self() const { return static_cast<D*>(this); }
template<class T>
void doWork_impl(T b) {
self()->a += b;
}
void doWork( double x ) override { doWork_impl(x); };
void doWork( int x ) override { doWork_impl(x); };
void doWork( long long x ) override { doWork_impl(x); };
};
struct DerA : public Base_helper<DerA> {
int a;
};
struct DerB : public Base_helper<DerB> {
double a;
};
note that every version of doWork must be valid to call on each of the Ders, as the Base_helper instantiates all of them.
If the kind of type passed to doWork is unbounded, yet the types of Der is bounded, you can do something like the above only backwards. It gets awkward, however. Your best bet in that kind of situation is to use a boost::variant type solution.
I guess you want to achieve something like this:
template<typedef T>
class Base {
T a;
void doWork(T b) { // Add another value to "a" which is of its same type
a += b; // For example; an operation that works on "a", no matter what numeric type it is
}
}
class DerA : public Base<int> {
}
class DerB : public Base<float> {
}
Or you can dump classes DerA and DerB entirely and use typedefs instead:
typedef Base<int> DerA;
typedef Base<float> DerB;
This can be easily solved with a CRTP-like pattern:
template<class D> // Base class is templated
class Base {
public:
D a;
void doWork(D b) {
a += b;
}
};
class DerA : public Base<int> {};
class DerB : public Base<float> {};
Live Example
Edit: in case you need only one common base (Base<int> is a completely different type from Base<float>) you might use an interface class and have Base inherit from it.

Override a data member in a C++ derived class

I have an doubt, with C++ redefinition. I assign memory in Derived class, so I need that this memory is reserved in Base class. So, I need considered that the attibute in the Base class is the same that the attribute in the Derived class, and I don't know is that is possible in C++.
class Base {
protected:
float * a;
Base() {}
public:
virtual void reset() {
a = 0;
}
virtual void exec() {
printf("Memory a: %x\n",a);
}
};
class Derivada: virtual public Base {
protected:
float * a;
Derivada() {}
virtual void reset() {
a = new float[256];
}
};
int main() {
Derivada *hija= new Derivada();
hija->reset();
hija->exec();
delete hija;
}
I really need do overloading, because it is an example of my real problem. I have the same test (Derived an main, code), for two different class Base, one in each branch, of my two branchs, of CVS.
In one of this class Base, I have this attributes, an in the other class Base, I don't have this attributes, so I have to put it, in Derived class, for compiling.
I wouldn't like to have to make two different test codes, so I need override the attribute
You could do something like this (but requires C++11):
#include <type_traits>
// A way to check for 'attr' data member presence/absence using SFINAE
template<class T> constexpr auto missing_attr(T) -> decltype(T::attr, bool())
{
return false;
}
constexpr bool missing_attr(...) { return true; }
struct Base { /* There might be (or not) a float data member 'attr' */ };
template<bool> struct Inject;
template<> struct Inject<true> { float attr = 0.0; };
template<> struct Inject<false> {};
struct Derived : public Base, protected Inject<missing_attr(Base())>
{
void do_something_with_attr()
{
// Derived has only one 'float attr' (it can be from Base or from Inject).
a *= a;
}
};
There are other ways to detect if a data member exists, e.g. the member detector idiom (C++03 compatible).
Do not redeclare the member the the derived class. The word "protected" ensures visibility.
If you redeclare the member, you will have a new member. This is called shadowing. See, e.g.
http://www-personal.umich.edu/~saarela/programming/2009/07/c-variable-shadowing.html
http://en.wikipedia.org/wiki/Variable_shadowing