Overriding overloaded member functions that call each other in cpp - c++

I have designed a class which uses overloaded member functions that call each other such that functions with additional arguments modify member variables that the original function relies on. It works as expected/intended when inheritance is not involved, but I found myself reusing the code often enough to want to create an abstract class.
I did this by having the original member function exit with an error in the abstract class, but still implementing the overloaded functions that modify member variables before calling the original function. This is done with the intent of only having to override the original function in my derived classes. However, when I create a derived class from this abstract class and supposedly override the member function, the functions that are not overridden still seem to be using the abstract class's definition of the member function-- the one that exits with an error. Here is a minimal example that causes the unexpected behavior.
#include <iostream>
#include <string>
#include <cstdlib>
class Base
{
// this class exists only to be derived from
public:
void write_message()
{
std::cerr << "Base is an abstract class not intended for direct use in"
<< " programs." << std::endl;
exit(1);
}
void write_message(std::string NewMessage)
{
Message = NewMessage;
write_message();
}
protected:
std::string Message = "This is the default message";
};
class Derived : public Base
{
public:
using Base::write_message;
void write_message()
{
std::cout << Message << std::endl;
}
private:
// intentionally blank
};
int main() {
Derived MyObject;
MyObject.write_message("Here is a modified message");
return 0;
}
As I'm sure is clear from this example, I am already aware of the common pitfall involving inheriting overloaded member functions which is topic of other questions on this site, which is needing to have using Base::write_message in my derived class. A couple of those questions include: this and this. What those questions don't address is this issue involving the overriding of write_message not working the way I expect it to.
What is missing here? I can't reason out why Base::write_message() would be used of Derived::write_message when calling MyObject.write_message("Here is a modified message"); in the code above.
I am using cpp17 and g++12.2.1 on linux.

What you should use is the virtual methods. Without them, it's not the overriding, but so called hiding. That's, you may define a method within the derived class which will have the same calling semantics as in base class, but it will hide the method from the base class.
Here is rewritten your example:
#include <iostream>
#include <string>
#include <cstdlib>
class Base
{
// this class exists only to be derived from
public:
virtual ~Base() = default; // It's better to have a virtual destructor if there is at least one virtual method.
virtual void write_message() = 0; // Pure virtual method. It defines the calling interface only and must be overridden to be used.
void write_message(const std::string& NewMessage) // It's better to use the const-reference in order to escape unneeded copying.
{
Message = NewMessage;
write_message(); // Call the _implementation_
}
protected:
std::string Message = "This is the default message";
};
class Derived : public Base
{
public:
using Base::write_message;
void write_message() override // 'override' key-word ensures that we are overriding 'right' method and helps against of typos etc.
{
std::cout << Message << std::endl;
}
private:
// intentionally blank
};
int main() {
// Yes, it points to the Base, but because of virtuality...
Base* MyObject = new Derived;
MyObject->write_message("Here is a modified message"); // ... it invokes the Derived::write_message() here.
delete MyObject; // Don't forget to free the memory.
return EXIT_SUCCESS;
}

Related

Operator<< in base class not visible in derived class [duplicate]

I am trying to understand why the following code does not compile, apparently the solution relies in specifically declaring the dependency on method_A in the derived class.
Please refer to the following code:
class Base
{
public:
void method_A(int param, int param2)
{
std::cout << "Base call A" << std::endl;
}
};
//does not compile
class Derived : public Base
{
public:
void method_A(int param)
{
std::cout << "Derived call A" << std::endl;
}
};
//compiles
class Derived2 : public Base
{
public:
using Base::method_A; //compile
void method_A(int param)
{
std::cout << "Derived call A" << std::endl;
}
};
int main ()
{
Derived myDerived;
myDerived.method_A(1);
myDerived.method_A(1,2);
Derived2 myDerived2;
myDerived2.method_A(1);
myDerived2.method_A(1,2);
return 0;
}
"test.cpp", (S) The wrong number of arguments have been specified for "Derived::method_A(int)".
What is the technical reason that prevents the derived class to know its base class is implementing the method it's trying to overload?
I am looking in understanding better how the compiler/linker behaves in this case.
Its called Name Hiding. When you define a non virtual method with the same name as Base method it hides the Base class method in Derived class so you are getting the error for
myDerived.method_A(1,2);
To avoid hiding of Base class methods in Derived class use using keyword as you did in Derived2 class.
Also if you want to make it work you can do it explictly
myDerived.Base::method_A(1,2);
Check out this for better explanation why name hiding came into picture.
Well, for one you're calling
myDerived.method_A(1,2);
with 2 arguments, whereas both in base and derived the method is declared to take only one argument.
Secodnly, you're not overriding anything, because method_A is not virtual. You're overloading.
If your intention is to override void Base::method_A(int param, int param2) then you should mark it virtual in the base class:
virtual void method_A(int param, int param2)
Any function overriding this must have the same parameters and almost the same return type ('almost' loosely meaning that the differing return types must be polymorphically related, but in most cases it should have the identical return type).
All you're currently doing is overloading the function in the base class. The using keyword is bringing the base class function into the child class' namespace, as the language behaviour is not to do this by default.

Intional use of name hiding for static function inheritance

I have a base class Base and a number of sub classes BaseDerivate1 .. BaseDerivateN. Part of my code is generic and supports any of the sub classes by accessing the used class via a define BASE_DERIVATE.
I now need to add a static function that the child classes can declare but don't have to. For derived classes that declare StaticFunc(), I want to call it. In all other cases, I want to call the fallback function Base::StaticFunc(). The call looks like this:
#define BASE_DERIVATE BaseDerivate1 // or some other child class
// somewhere else:
BASE_DERIVATE::StaticFunc();
So I intentionally use name hiding here. The StaticFunc is never called from within the class. The question I have is: Is this supported by the C++ standard or would this lead to compiler errors for some compilers. Also: Is there a better way to do "static inheritance"? I am stuck with the define BASE_DERIVATE concept however.
This will "just work":
#include <iostream>
class Base {
public: static void foo() { std::cout << "Base::foo()\n"; }
};
class Derived1 : public Base { };
class Derived2 : public Base {
public: static void foo() { std::cout << "Derived2::foo()\n"; }
};
int main() {
Derived1::foo(); // prints "Base::foo()"
Derived2::foo(); // prints "Derived2::foo()"
}
It's the use of regular name shadowing, which works just the same for static members. The Base static implemenation is still available from Derived2 by means of rather funny syntax:
Derived2::Base::foo();

C++ : Automatically run function when derived class is constructed

So I recently accidentally called some virtual functions from the constructor of a base class, i.e. Calling virtual functions inside constructors.
I realise that I should not do this because overrides of the virtual function will not be called, but how can I achieve some similar functionality? My use-case is that I want a particular function to be run whenever an object is constructed, and I don't want people who write derived classes to have to worry about what this is doing (because of course they could call this thing in their derived class constructor). But, the function that needs to be called in-turn happens to call a virtual function, which I want to allow the derived class the ability to override if they want.
But because a virtual function gets called, I can't just stick this function in the constructor of the base class and have it get run automatically that way. So I seem to be stuck.
Is there some other way to achieve what I want?
edit: I happen to be using the CRTP to access other methods in the derived class from the base class, can I perhaps use that instead of virtual functions in the constructor? Or is much the same issue present then? I guess perhaps it can work if the function being called is static?
edit2: Also just found this similar question: Call virtual method immediately after construction
If really needed, and you have access to the factory.
You may do something like:
template <typename Derived, typename ... Args>
std::unique_ptr<Derived> Make(Args&&... args)
{
auto derived = std::make_unique<Derived>(std::forward<Args>(args));
derived->init(); // virtual call
return derived;
}
There is no simple way to do this. One option would be to use so-called virtual constructor idiom, hide all constructors of the base class, and instead expose static 'create' - which will dynamically create an object, call your virtual override on it and return (smart)pointer.
This is ugly, and what is more important, constrains you to dynamically created objects, which is not the best thing.
However, the best solution is to use as little of OOP as possible. C++ strength (contrary to popular belief) is in it's non-OOP specific traits. Think about it - the only family of polymorphic classess inside standard library are streams, which everybody hate (because they are polymorphic!)
I want a particular function to be run whenever an object is constructed, [... it] in-turn happens to call a virtual function, which I want to allow the derived class the ability to override if they want.
This can be easily done if you're willing to live with two restrictions:
the constructors in the entire class hierarchy must be non-public, and thus
a factory template class must be used to construct the derived class.
Here, the "particular function" is Base::check, and the virtual function is Base::method.
First, we establish the base class. It has to fulfill only two requirements:
It must befriend MakeBase, its checker class. I assume that you want the Base::check method to be private and only usable by the factory. If it's public, you won't need MakeBase, of course.
The constructor must be protected.
https://github.com/KubaO/stackoverflown/tree/master/questions/imbue-constructor-35658459
#include <iostream>
#include <utility>
#include <type_traits>
using namespace std;
class Base {
friend class MakeBase;
void check() {
cout << "check()" << endl;
method();
}
protected:
Base() { cout << "Base()" << endl; }
public:
virtual ~Base() {}
virtual void method() {}
};
The templated CRTP factory derives from a base class that's friends with Base and thus has access to the private checker method; it also has access to the protected constructors in order to construct any of the derived classes.
class MakeBase {
protected:
static void check(Base * b) { b->check(); }
};
The factory class can issue a readable compile-time error message if you inadvertently use it on a class not derived from Base:
template <class C> class Make : public C, MakeBase {
public:
template <typename... Args> Make(Args&&... args) : C(std::forward<Args>(args)...) {
static_assert(std::is_base_of<Base, C>::value,
"Make requires a class derived from Base");
check(this);
}
};
The derived classes must have a protected constructor:
class Derived : public Base {
int a;
protected:
Derived(int a) : a(a) { cout << "Derived() " << endl; }
void method() override { cout << ">" << a << "<" << endl; }
};
int main()
{
Make<Derived> d(3);
}
Output:
Base()
Derived()
check()
>3<
If you take a look at how others solved this problem, you will notice that they simply transferred the responsibility of calling the initialization function to client. Take MFC’s CWnd, for instance: you have the constructor and you have Create, a virtual function that you must call to have a proper CWnd instantiation: “these are my rules: construct, then initialize; obey, or you’ll get in trouble”.
Yes, it is error prone, but it is better than the alternative: “It has been suggested that this rule is an implementation artifact. It is not so. In fact, it would be noticeably easier to implement the unsafe rule of calling virtual functions from constructors exactly as from other functions. However, that would imply that no virtual function could be written to rely on invariants established by base classes. That would be a terrible mess.” - Stroustrup. What he meant, I reckon, is that it would be easier to set the virtual table pointer to point to the VT of derived class instead of keep changing it to the VT of current class as your constructor call goes from base down.
I realise that I should not do this because overrides of the virtual function will not be called,...
Assuming that the call to a virtual function would work the way you want, you shouldn't do this because of the invariants.
class B // written by you
{
public:
B() { f(); }
virtual void f() {}
};
class D : public B // written by client
{
int* p;
public:
D() : p( new int ) {}
void f() override { *p = 10; } // relies on correct initialization of p
};
int main()
{
D d;
return 0;
}
What if it would be possible to call D::f from B via VT of D? You will use an uninitialized pointer, which will most likely result in a crash.
...but how can I achieve some similar functionality?
If you are willing to break the rules, I guess that it might be possible to get the address of desired virtual table and call the virtual function from constructor.
Seems you want this, or need more details.
class B
{
void templateMethod()
{
foo();
bar();
}
virtual void foo() = 0;
virtual void bar() = 0;
};
class D : public B
{
public:
D()
{
templateMethod();
}
virtual void foo()
{
cout << "D::foo()";
}
virtual void bar()
{
cout << "D::bar()";
}
};

What is the term for an inheriting class constructor with different parameters?

Take the example below. What term do you use to describe an inheriting class with different parameters then the base class? I understand that subbase is implicitly calling base(). You wouldn't call this overriding, correct, since the base constructor is still called?
#include <iostream>
#include <stdio.h>
#include <string>
using namespace std;
class base
{
public:
base()
{
cout << "Hello!\n";
}
};
class subbase : public base
{
public:
subbase(string s)
{
cout << s << endl;
}
};
int main()
{
subbase test("Hello World!\n");
return 0;
}
Overloaded my friend. It has same method name but differing parameter or return type
But in this case you are just creating whole new constructor. Not really inheriting or anything.
Overloading: When you change the signature of the inherited functions in the derived class.
Redefinition(In case of normal functions)/Overriding(In case of virtual functions): When you keep the signature of the base class functions same in the derived class. But you change the implementation part.
But I am not talking in terms of Constructors here. I am talking about the usual member functions of the class.

overloading base class method in derived class

I am trying to understand why the following code does not compile, apparently the solution relies in specifically declaring the dependency on method_A in the derived class.
Please refer to the following code:
class Base
{
public:
void method_A(int param, int param2)
{
std::cout << "Base call A" << std::endl;
}
};
//does not compile
class Derived : public Base
{
public:
void method_A(int param)
{
std::cout << "Derived call A" << std::endl;
}
};
//compiles
class Derived2 : public Base
{
public:
using Base::method_A; //compile
void method_A(int param)
{
std::cout << "Derived call A" << std::endl;
}
};
int main ()
{
Derived myDerived;
myDerived.method_A(1);
myDerived.method_A(1,2);
Derived2 myDerived2;
myDerived2.method_A(1);
myDerived2.method_A(1,2);
return 0;
}
"test.cpp", (S) The wrong number of arguments have been specified for "Derived::method_A(int)".
What is the technical reason that prevents the derived class to know its base class is implementing the method it's trying to overload?
I am looking in understanding better how the compiler/linker behaves in this case.
Its called Name Hiding. When you define a non virtual method with the same name as Base method it hides the Base class method in Derived class so you are getting the error for
myDerived.method_A(1,2);
To avoid hiding of Base class methods in Derived class use using keyword as you did in Derived2 class.
Also if you want to make it work you can do it explictly
myDerived.Base::method_A(1,2);
Check out this for better explanation why name hiding came into picture.
Well, for one you're calling
myDerived.method_A(1,2);
with 2 arguments, whereas both in base and derived the method is declared to take only one argument.
Secodnly, you're not overriding anything, because method_A is not virtual. You're overloading.
If your intention is to override void Base::method_A(int param, int param2) then you should mark it virtual in the base class:
virtual void method_A(int param, int param2)
Any function overriding this must have the same parameters and almost the same return type ('almost' loosely meaning that the differing return types must be polymorphically related, but in most cases it should have the identical return type).
All you're currently doing is overloading the function in the base class. The using keyword is bringing the base class function into the child class' namespace, as the language behaviour is not to do this by default.