Inheritance with Overloaded Functions That Rely on Pure Virtual Functions - c++

I have a base Write class that has a pure virtual function write (std::string text) that requires all derived classes to implement it. In the base class, there is an overloaded write function that takes in an int and calls the pure virtual write().
In the derived class, we implement the write (std::string text), as required.
In the main, I'm able to call console.write("dog\n");, but I'm not able to call it with the overloaded version that takes in an int without going through the base class name Write. Is there anyway to define this inheritance so that both write functions, one that takes in a std::string and one that takes in an int without giving away the details of the inheritance by going through the Write class name, as shown on the last line of the program?
I don't want the user to be able to call the overloaded write(int)' through theWrite` class name, if possible.
#include <iostream>
class Write
{
protected:
virtual void write (const std::string &text) = 0;
public:
void write (const int &number)
{
write (std::to_string (number));
}
};
class Console_Write : public Write
{
public:
void write (const std::string &text) override
{
std::cout << text;
}
};
int main()
{
Console_Write console;
console.write("dog\n");
console.Write::write (1); // Is it possible to be able to change the inheritance so we can just call: console.write (1);
}

The normal pattern for this would be having your base class look something like:
class Write {
public:
virtual ~Write() = default;
void write(const std::string& str) {
write_internal(str);
}
void write(int n) {
write(std::to_string(n));
}
private:
virtual void write_internal(const std::string& str) = 0;
}
class ConsoleWrite : public Write {
public:
~ConsoleWrite() = default;
private:
void write_internal(const std::string& str) {
std::cout << str;
}
}
The pattern even has a name "Non-Virtual Interface" - https://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Non-Virtual_Interface has more information about the pattern.

Related

How Call child method from parent class

I did a small exemple to try to explain you with my poor english what I want to do :).
I have a main class who is my engine. This is my parent class of several children.
this is the parent class :
#include <string>
#include <iostream>
#include <vector>
template <typename Type>
class A
{
public:
A(std::string const &str)
: m_str(str)
{
}
void run(void) const {
unsigned int i;
for(i = 0; ACTIONS[i].f != nullptr; i++) {
if(m_str == ACTIONS[i].key) {
return ((*(this).*ACTIONS[i].f)(m_str));
}
}
}
protected:
typedef struct s_action {
std::string key;
void (Type::*f)(std::string const &);
} t_action;
static t_action const ACTIONS[];
std::string m_str;
};
class B : public A<B>
{
public:
B(std::string const &str);
protected:
static t_action const ACTIONS[];
void error(std::string const &str);
void success(std::string const &str);
};
I would like to call children method with table pointer of member function in this parent class A::run as you can see above
This code does not compile.
I know it's not possible to have a static variable virtual, but it's
exactly that I need to do have for A::ACTIONS. I absolutely need to initialise B::ACTIONS to A::run works.
In first Is it possible? Have you got a small exemple of this case?
This is the end of my small code :
#include "Class.hpp"
B::t_action const B::ACTIONS[] = {
{"ERROR", &B::error},
{"SUCCESS", &B::success},
{"", nullptr}
};
B::B(std::string const &str)
: A<B>(str)
{
}
void B::error(std::string const &str) {
std::cerr << str << std::endl;
}
void B::success(std::string const &str) {
std::cout << str <<std::endl;
}
And the main:
#include "Class.hpp"
int main() {
B b("SUCCESS");
b.run();
return (0);
}
I didn't try, normally this code should Display SUCCESS on stdout
Thank you for your help
void run(void) const
{
unsigned int i;
for(i = 0; ACTIONS[i].f != nullptr; i++)
if (m_str == ACTIONS[i].key)
return ((*(this).*ACTIONS[i].f)(m_str));
}
There are multiple reasons why this fails to compile. Not one, but several reasons. This entire dispatching mechanism must be completely redesigned.
The first order of business is that this is a
void run(void) const
A const class method.
The method pointer in question is:
void (Type::*f)(std::string const &);
The method pointer is not const, but mutable. From an existing const class method, you can only invoke other const methods. You cannot invoke non-const methods, either directly or indirectly via a method pointer, from a const class methods.
So the first order of business is to change this to
void (Type::*f)(std::string const &) const;
This also means that all your methods, in the child class, error() and success(), must also be const class methods too.
If it's necessary to use this dispatch mechanism with non-const methods, the run() method cannot be a const class method itself. But this is not the only problem here, so I'll continue with the const method, at hand.
return ((*(this).*ACTIONS[i].f)(m_str));
The this here, is a A<Type>. This is a method of that class. That's what this is here.
The method pointer, f is pointer to a method of Type, not A<Type>. Type is a subclass of A<Type>, and you cannot convert a pointer or a reference to a base class to a pointer or a reference to a subclass, any more than you can take a pointer to A, and convert to a pointer to B when B inherits from A. C++ does not work this way.
The solution is simple, and requires only a few small tweaks. This run() should take a reference to const Type &, and invoke the method via the passed-in reference, then a replacement abstract run() method invokes it, passing *this as a parameter:
public:
virtual void run()=0;
protected:
void run_me(const Type &me) const
{
unsigned int i;
for(i = 0; ACTIONS[i].f != nullptr; i++)
if (m_str == ACTIONS[i].key)
return ((me.*ACTIONS[i].f)(m_str));
}
Then, each subclass that inherits this template only needs to implement a simple facade:
class B : public A<B>
{
public:
void run() const override
{
run_me(*this);
}
EDIT: This addresses the compilation error, but additional work is needed to deal with the fact that static class members cannot be overridden. The solution is also pretty simple: also leverage virtual class methods in order to implement this.
Remove the declaration of ACTIONS from the template base class, and replace it with an abstract function:
virtual const t_action *get_actions() const=0;
And use it in run_me():
const t_action *ACTIONS=this->get_actions();
The rest of run_me() remains as is, and then implement get_actions() in the child class:
const t_action *get_actions() const override
{
return ACTIONS;
}
Pretty much everything else remains the same.
The problem is that A will always use is own defined set of actions, not B's.
You don't need to create A at all, as you want to use B methods and list of methods.
Let's say that you create first a run call function:
template<typename T>
void run(T* obj, const std::string method)
{
const auto& available_methods = obj->get_methods();
auto iter = available_methods.find(method);
if(iter == available_methods.end())
{
// Handle this case
}
std::invoke(iter->second, obj); //C++17, or (obj->*(iter->second))();
}
Now for the class B, you need something very simple:
class B
{
public:
typedef std::unordered_map<std::string, void(B::*)()> MethodMap;
void foo();
static MethodMap& get_methods()
{
static MethodMap map{{"foo", &B::foo}};
return map;
}
};
Populate the map with get_methods() in the static function, and then call run through:
int main()
{
B b;
run(&b, "foo");
}
If you are going to use CRTP, IMO you need to google for CRTP first.
By the way here's a quick direct ans 2 your q:
template<typename crtp_child>
class crtp_base{
using crtp_target=crtp_child;
auto crtp_this(){
return static_cast<crtp_target*>(this);
};
auto crtp_this() const {
return static_cast<crtp_target const*>(this);
};
public:
void run(){
auto range=crtp_this()->actions.equal_range(m_str);
for(auto entry:range)
(crtp_this()->*(entry.second))(m_str);
};
protected:
crtp_base(std::string str):
m_str(str)
{};
std::string m_str;
//...
};
struct crtp_user:
crtp_base<crtp_user>
{
using crtp_base::crtp_base;//ctor fwding
protected:
friend class crtp_base<crtp_user>;
std::unordered_multimap<std::string, void (crtp_user::*)(std::string)> actions;
//...
};

C++ "overload virtual warning" when implementing interface

Here is my example code:
class Interface {
public:
virtual void foo(const Interface &interface) = 0;
};
class A : public Interface {
public:
void foo(const A &a) {
// do something with another object of same type
}
};
class B : public Interface {
public:
void foo(const B &b) {
}
};
There is a warning:
warning: 'A::foo' hides overloaded virtual function
[-Woverloaded-virtual]
void foo(const A &a) {
^
note: hidden overloaded virtual function 'Interface::foo'
declared here: type mismatch at 1st parameter ('const Interface &' vs
'const A &')
virtual void foo(const Interface &interface) = 0;
How to deal with the problem? Is adding using Interface::foo; in derived class the best solution? I think it's a common problem. Thanks a lot!
void foo(const A &a) does not override void foo(const Interface &interface). While the language allows covariant return types, you can't have covariant parameters as far as I know.
So your void foo(const A &a) is hiding (or at most overloading) the base version of the function.
If you use C++11's override keyword, the compiler should more clearly tell you that you aren't overriding. Or if you try to instantiate an A then it should fail with an error about A being abstract because it hasn't actually overridden foo.
The solution of course is to make the derived versions use the exact same parameter types for foo.
The virtual part of your virtual void foo() function indicates that it can be overridden in a class that inherits Interface. In class A and B, you have used the same function but changed the parameters, which means that the function will be overloaded.
If you want to just override the function in the sub classes, use void foo(const Interface &interface).
For more details on overloading virtual functions see this post: Overloading a virtual function in a child class
Thanks #GargAnkit in comment,Here is my total solotion:
#include <iostream>
#include <string>
using std::cout;
using std::endl;
class Interface {
public:
int compare(const Interface &that) const {
if (this->to_string() < that.to_string()) {
return -1;
} else if (this->to_string() == that.to_string()) {
return 0;
} else {
return 1;
}
}
virtual std::string to_string() const = 0;
};
class A : public Interface {
public:
std::string to_string() const override {
return "A";
}
};
class B : public Interface {
public:
std::string to_string() const override {
return "B";
}
};
int main() {
A a;
B b;
cout << a.compare(b) << endl;
cout << "ok" << endl;
return 0;
}
For a function to be picked as an override of a function in the base class, both function must match exactly - same name, same parameters, same const/volatile qualification. If the function only differ by the qualification, they will be seen as totally non correlated functions, and the base function will not consider as overriden.
example::
**
class A
{
public:
virtual void fun(..)const{}
};
class B:public A
{
public:
void fun(..){} //violation
};
**

Namespace-like access in class

For a container class I'd like to provide an interface with several functions which are grouped into categories, for example:
Data::Get::FirstGetter()
Data::Get::SecondGetter()
Data::Set::FirstSetter()
Data::Set::FirstSetter()
This would allow for something like this:
Data myData;
myData::Set::FirstSetter( stuff );
std::cout << myData::Get::FirstGetter() << std::endl; // -> "stuff"
Obviously the code itself is bogus and I've used the scope operator :: as a potential placeholder for something else (I am aware that you can not create namespaces within a class).
An approach to achieve something like this is demonstrated in the following snippet:
#include <iostream>
struct Foo {
private:
struct aBar {
void IFunc(){
std::cout << "IFunc()" << std::endl;
}
};
public:
void OFunc(){
std::cout << "OFunc()" << std::endl;
}
aBar Bar;
};
int main(){
Foo foo;
foo.OFunc();
foo.Bar.IFunc();
}
However, in order to use this, one must create an instance of each grouping object (in the pseudocode example one instance of Get and another one of Set, in the dummy example one instance of aBar). Is there a way to achieve this functionality in a different way (maybe using the actual scope operator :: to indicate the member that is to be called resides within an inner scope)?
I don't really understand the reason why you want to achieve such a behaviour. However, if you want to achieve something like that you may get inspired by the following (although I won't ever use some code like this in any project, still not seeing one plausible reason):
#include <iostream>
class Interface1
{
protected:
virtual ~Interface1() {}
virtual void DoStuff1() = 0;
};
class Interface2
{
protected:
virtual ~Interface2() {}
virtual void DoStuff2() = 0;
};
class Interface3
{
protected:
virtual ~Interface3() {}
virtual void DoStuff3() = 0;
};
class Container;
class Grouper1
{
public:
static void DoStuff1(Container& arContainer);
static void DoStuff2(Container& arContainer);
};
class Grouper2
{
public:
static void DoStuff3(Container& arContainer);
};
class Container : public Interface1, public Interface2, public Interface3
{
public:
virtual ~Container() {}
private:
friend class Grouper1;
friend class Grouper2;
virtual void DoStuff1() { printf("DoStuff1()\n"); }
virtual void DoStuff2() { printf("DoStuff2()\n"); }
virtual void DoStuff3() { printf("DoStuff3()\n"); }
};
void Grouper1::DoStuff1(Container& arContainer) { arContainer.DoStuff1(); }
void Grouper1::DoStuff2(Container& arContainer) { arContainer.DoStuff2(); }
void Grouper2::DoStuff3(Container& arContainer) { arContainer.DoStuff3(); }
int main(int aArgc, char** aArgv)
{
Container c;
Grouper1::DoStuff1(c);
Grouper1::DoStuff2(c);
Grouper2::DoStuff3(c);
return 0;
}
This way your Container can implement some interfaces and your Groupers provide static functions (grouped) to access those methods (although you need to pass the actual Container, you want to work on). But definitely you won't achieve namespace-like access if you don't provide some helper functions/classes (as Grouper1, Grouper2).

Adding Functionality To An Object Without Changing The Interface

I have an object presented as a reference/pointer to an interface. I would like to call a method on the concrete object if that method is present, without changing the interface, breaking encapsulation, or writing any horrible hacks. How can it be done?
Here's an example.
I have an interface:
class IChatty
{
public:
virtual ~IChatty() {};
virtual std::string Speak() const = 0;
};
And multiple concrete implementation of this interface:
class SimpleChatty : public IChatty
{
public:
~SimpleChatty() {};
virtual std::string Speak() const override
{
return "hello";
}
};
class SuperChatty : public IChatty
{
public:
void AddToDictionary(const std::string& word)
{
words_.insert(word);
}
virtual std::string Speak() const override
{
std::string ret;
for(auto w = words_.begin(); w != words_.end(); ++w )
{
ret += *w;
ret += " ";
}
return ret;
}
private:
std::set<std::string> words_;
};
The SuperChatty::AddToDictionary method is not present in the abstract IChatty interface, although it could be included in another, new interface.
In the real world, these objects are constructed through factories, themselves concrete instantiations of an abstract interface. However for our purposes that's orthogonal to the problem at hand:
int main()
{
IChatty* chatty = new SuperChatty;
chatty->AddToDictionary("foo");
std::cout << chatty->Speak() << std::endl;
}
Since AddToDictionary isn't part of the IChatty interface (and can't be part of it), I can's call it.
How can I call AddToDictionary on the chatty pointer without breaking encapsulation, writing some horrible hack, or taking any other design shortcuts?
NOTE: In the real world, the dictionary is part of the SuperChatty object itself, and cannot be separate from it.
NOTE2: I do not want to downcast to the concrete type.
Have dictionary be an object which can be updated and referenced by SuperChatty:
class Dictionary {
public:
void add(const std::string& word);
const std::set<std::string>>& words() const;
//..
};
class SuperChatty : public IChatty
{
public:
SuperChatty(Dictionary& dictionary) :
dictionary(dictionary) {
}
virtual std::string Speak() const override
{
auto words = dictionary.words();
ostringstream oss;
copy(words.begin(), words.end(),
ostream_iterator<string>(oss, " "));
return oss.str();
}
};
Usage:
int main()
{
Dictionary dictionary;
IChatty* chatty = new SuperChatty(dictionary);
dictionary.add("foo");
std::cout << chatty->Speak() << std::endl;
}
edit
Okay, the question changed.
If you're doing this properly, you need to isolate yourself from the bad underlying system:
struct Dictionary {
virtual ~Dictionary () {}
virtual void add(const std::string& word) = 0;
};
struct Instrumenter {
virtual ~Instrumenter () {}
virtual void addDictionary(Dictionary& dictionary) = 0;
};
struct Chatter {
virtual ~Chatter() {}
virtual string speak() const = 0;
virtual void instrument(Instrumenter& instrumenter) = 0;
};
These are implemented as:
class BasicChatter : public Chatter {
virtual string speak() const {
return chatty.Speak();
}
virtual void instrument(Instrumenter& instrumenter) {
// do nothing
}
private:
SimpleChatty chatty;
};
class SuperChatter : public Chatter {
SuperChatter () : dictionary(chatty);
virtual void instrument(Instrumenter& instrumenter) {
instrumenter.addDictionary(dictionary);
}
virtual string speak() const {
return chatty.Speak();
}
private:
SuperChatty chatty;
DictionaryImpl dictionary;
};
Make it derive from another interface and simply check, whether you can cast the object to that interface or not.
class IDictionary
{
public:
virtual ~IDictionary() {};
virtual void AddToDictionary(const std::string& word) = 0;
};
class SuperChatty : public IChatty, public IDictionary
{
... as before ...
};
int main()
{
IChatty* chatty = new SuperChatty;
IDictionary *dict = dynamic_cast<IDictionary*>(chatty);
if (dict) dict->AddToDictionary("foo");
std::cout << chatty->Speak() << std::endl;
}
The main problem is that you're trowing away information that you need.
So the main solution is to not throw away information, but there's not enough code presented to flesh out the details of that.
Secondly, a tehcnical kludge solution is to just downcast, using dynamic_cast:
IChatty* newThingy();
int main()
{
IChatty* chatty = newThingy();
if( SuperChatty* p_super_chatty = dynamic_cast<SuperChatty*>( chatty ) )
{
p_super_chatty->AddToDictionary("foo");
}
std::cout << chatty->Speak() << std::endl;
}
You can downcast safely because the know static type IChatty is polymorphic.
For this particular example, there's no reason to not create the object as this:
SuperChatty* chatty = new SuperChatty;
chatty->AddToDictionary("foo");
You can still pass chatty in the above segment as IChatty pointer or reference, e.g.
void Talk(IChatty *ch)
{
ch->Speak();
}
[Likewise for storing the chatty in a vector<IChatty*> or something like that].
My point here is that if you are going to use the "new" interface functions, then you probably also want to create the class that has the new interface.
Adding code to "try to cast it", etc, gets very messy very quickly, and is error prone.

Basic question about polymorphism. Vector of base class, want the derived class. How?

I think I messed up somehow in my design because I want to keep a vector of various object types. These types all share a common base class. Example:
Class Buick: AmericanCar
{
}
Class Ford: AmericanCar
{
}
then I did:
vector<AmericanCar*> cars_i_own;
Now, I have my vector of pointers but I don't have the derived class which is what I need. I thought about adding a GetType/SetType function to the base class and then use a dynamic cast. This is clunky though. Did i use the wrong design for this?
Well, what are you trying to do with it? Get the name or cost? You would have something like:
class Car
{
public:
virtual ~Car(void) {}
virtual std::string location(void) const = 0;
virtual std::string name(void) const = 0;
virtual double cost(void) const = 0;
}
class AmericanCar
{
public:
virtual ~AmericanCar(void) {}
virtual std::string location(void) const
{
return "America";
}
}
class Buick : public AmericanCar
{
public:
virtual std::string name(void) const
{
return "Buick";
}
virtual double cost(void) const
{
return /* ... */;
}
}
class Ford : public AmericanCar
{
public:
virtual std::string name(void) const
{
return "Ford";
}
virtual double cost(void) const
{
return /* ... */;
}
}
Now you can call these methods polymorphically.
This is somewhat strange, though. You don't need a different class to store names and cost like this:
class Car
{
public:
Car(const std::string& pLocation,
const std::string& pName,
double pCost) :
mLocation(pLocation),
mName(pName),
mCost(pCost)
{
}
const std::string& location(void) const
{
return mLocation;
}
void location(const std::string& pLocation)
{
mLocation = pLocation;
}
const std::string& name(void) const
{
return mName;
}
void name(const std::string& pName)
{
mName = pName;
}
const double cost(void) const
{
return mCost;
}
void cost(double pCost)
{
mCost = pCost;
}
private:
std::string mLocation;
std::string mName;
double mCost;
}
// make cars
std::vector<Car> cars;
cars.push_back(Car("America", "Buick", /* ... */));
The purpose of inheritance / polymorphism is so you don't need to care which derived type you are dealing with.
In particular I think storing data, such as make of car, country of origin etc, encoded in a class hierarchy doesn't seem to be particularly beneficial. Does an AmericanCar do something fundamentally different from, say, a Japanese car (other than consuming more fuel, which again can be better stored in a data member)?
Why do you need to know the derived class? Normally you would have virtual functions to take care of any behavior differences between the two derived classes.
The goal is that the code using the parent class shouldn't have to know the exact class it's working with.
You can use typeid to determine the derived class:
struct Base
{
virtual ~Base() {}
};
struct Derived : public Base { };
int main()
{
Base* b = new Derived();
std::cout << typeid(*b).name() << std::endl;
}
This outputs: "Derived".
But, usually with polymorphism the point is that you shouldn't be concerned with this. You simply call a base-class member function and the proper derived-class member function is called at runtime.