So I was wondering if it is possible in C++ to call a parent class method that uses an overridden method without using the parent version of the overridden method. (I know this is unclear so I made an example!)
For example, below I would like to call class A's version of findPath() from an object of class B, while using the addPoint method that is defined by class B. Currently, if I call findPath() from an object of class B, it uses the addPoint method defined in class A.
Actual Output:
A.findPath(), path = {1,2,3,4,5,6,7,8,9,10)
B.findPath(), path = {1,2,3,4,5,6,7,8,9,10)
Desired Output:
A.findPath(), path = {1,2,3,4,5,6,7,8,9,10}
B.findPath(), path = {2,4,9,16,25,36,49,64,81,100}
class A
{
public:
vector<int> path;
void addPoint(int num) {
path.push_back(num);
}
vector<int> findPath() {
for (int i = 0; i < 10; i++) {
addPoint(i);
}
}
};
class B : public A
{
public:
void addPoint(int num) {
path.push_back(num*num);
}
};
At the moment, I am copying and pasting findPath into class B to get the desired output, but I feel like there should be an easier way. Thanks!
You need to use virtual in the base class. You should also add override in the derived class, compare the CppCoreGuidelines.
class A
{
public:
...
virtual void addPoint(int num) {
path.push_back(num);
}
...
};
class B : public A
{
public:
void addPoint(int num) override {
path.push_back(num*num);
}
};
It is possible. This is known as the Template Method Pattern. The name is a bit unfortunate, because it has nothing to do with C++ templates. A base class can implement something and derived classes only override the individual steps of the bigger "something".
For example:
struct Base {
virtual void stepA() = 0;
virtual void stepB() = 0;
virtual void stepC() = 0;
void do_something_complicated() {
stepA();
stepB();
stepC();
}
};
Derived classes only override the methods for the individual steps, while they are composed in the base class already.
In your example you forgot to declare addPoint as virtual, A should have a virtual destructor and using override is recommended to let the compiler help you in case of mistakes:
class A
{
public:
vector<int> path;
virtual void addPoint(int num) {
path.push_back(num);
}
vector<int> findPath() { // () was missing
for (int i = 0; i < 10; i++) {
addPoint(i);
}
return path; // return was missing
}
virtual ~A() = default;
};
class B : public A
{
public:
void addPoint(int num) override {
path.push_back(num*num);
}
};
Related
I learn C++ OOP-paradigm and want to ask related question:
Assumption
We have a base class:
class Base {
public:
virtual SomeType PowerMethod() { return SomeType{} };
}
We have a variable target and subclass which realizes some calculations with target variable based on the constructor's parameter (simple calculations or complicated calcs):
class Calc : public Base {
public: // using only public access to simplify real code structure
SomeType target;
void Simple() { target = 1; };
void Complex(){ target = 10000; };
explicit Calc(bool isSimple) {
if(isSimple)
Simple();
else
Complex();
}
};
Question
How to optimally realize two classes which based on different methods (Simple or Complex) but provide the same functionality of PowerMethod()?
My solution
class SimpleCalc : public Calc {
bool isSimple = true;
public:
SomeType PowerMethod() override {
Calc CalcInstance(isSimple);
return CalcInstance.target;
};
};
class ComplexCalc : public Calc {
bool isSimple = false;
public:
SomeType PowerMethod() override {
Calc CalcInstance(isSimple);
return CalcInstance.target;
};
};
This solution is pretty "ugly" and I want to ask you how to make it more readable.
Thank you!
I think that in your code, you didn't mean to craete a new Calc object, but instead call it on the superclass. This can be done like so:
Calc::Simple();
You can override the method PowerMethod, but still call the superclass's code:
virtual SomeType PowerMethod() override {
//do something
Base::PowerMethod();
}
If your problem is more complicated, and polymorphism and superclasses can't help you, you can always declare some method protected, so that only subclasses can access it. So, you could for example do this:
class Calc : public Base {
protected:
SomeType target;
void Simple() { target = 1; };
void Complex(){ target = 10000; };
public:
explicit Calc(bool isSimple) {
if(isSimple)
Simple();
else
Complex();
}
};
class SimpleCalc : public Calc {
public:
SomeType PowerMethod() override {
Calc::Simple();
return Calc::target;
};
};
class ComplexCalc : public Calc {
public:
SomeType PowerMethod() override {
Calc::Complex();
return Calc::target;
};
};
If your target is to learn OOP then you can use a factory design pattern to create your final calculator based on isSimple condition:
#include <iostream>
class Base
{
public:
Base()
{
target = 0;
}
int target;
virtual void PowerMethod() = 0;
};
class SimpleCalc : public Base
{
virtual void PowerMethod() { target = 0; }
};
class ComplexCalc : public Base
{
virtual void PowerMethod() { target = 1000; }
};
class CalcFactory
{
public:
virtual Base* createCalc(bool isSimple)
{
if (isSimple)
return new SimpleCalc();
else
return new ComplexCalc();
}
};
int main()
{
CalcFactory factory;
Base * base1 = factory.createCalc(true);
Base * base2 = factory.createCalc(false);
base1->PowerMethod();
base2->PowerMethod();
std::cout << base1->target << std::endl;
std::cout << base2->target << std::endl;
}
I'm working on a small project, and I found myself in a situation like this :
class A{}
class B : class A {
public:
void f();
int getType() const;
private:
int type;
}
class C : class A{
public:
int getType() const;
private:
int type;
}
I want to know if there's a way to call the f() function (in class B) from an object of type A?
I tried this but it says function f() cannot be found in class A :
int main(){
vector<A*> v;
// v initialized with values of A ...
if (v->getType() == 1){ // 1 is the type of B
v->f();
}
}
As you've seen, this code won't compile because A doesn't have an f method. In order to make it work, you'd have to explicitly downcast the pointer:
B* tmp = dynamic_cast<B*>(v);
tmp->f();
To begin with, with your current classes, you can't call getType() on an A*. Because the interface of A doesn't have this method. To solve this problem, you either need to make getType a virtual function in A, or move the type field to base class A (as protected) and initialize it in the constructors of the child classes. Let me show you the first method, because I think it is a better approach, since it makes the objective of this function more clear.
class A {
public:
virtual int getType() { return 0; } // or delete the function: ... getType() = 0;
}
class B : public A {
public:
int getType() override { return 1; }
}
With these classes, once you create an instance of B, getType() returns 1 when called on that instance, whether it is pointed to by an A* or B*:
A *object = new B();
object->getType(); // returns 1
Now, if you need to access the f() from B, you can again add it as a virtual method to A's interface, or make a cast to B*.
Using a virtual method:
class A {
public:
virtual void f() { /* a default action maybe? */ }
}
class B : public A {
public:
void f() /* override if you want */ { /* whatever this function does in B */ }
}
...
for (A *ptr : v)
ptr->f();
Using a cast:
class A {
public:
virtual int getType() { return 0; }
}
class B : public A {
public:
void f();
int getType() override { return 1; }
}
...
for (A *ptr : v)
if (ptr->getType() == 1)
dynamic_cast<B*>(ptr)->f();
TL;DR
I am trying to pass a subclass into a function that expects the subclass's base class and then store a unique pointer of that base class in a vector in a third, completely separate class.
(C++ 11 and higher)
End TL;DR
I have 3 classes total and then my int main().
The base (abstract) class has a constructor and a virtual function.
The base class constructor is implemented, the virtual function is not.
The second class is the subclass to the base class.
It implements its own constructor and calls the base constructor.
The second part of the sub class is the concrete implementation of the virtual base class function.
I then have a third class that has its own constructor.
This third class has a function whose function header contains a reference to the base class.
This same function then tries to pass this reference to the abstract class and then .push_back() the reference into a vector of std::unique_ptr of this abstract class.
(Because I cannot directly have a vector of abstract class instances.)
My issue is that I am currently unable to get a version of this code to compile.
I have been referencing some resources online to try to solve my problem.
pass unique_ptr as an object
https://stackoverflow.com/questions/8114276/how-do-i-pass-a-unique-ptr-argument-to-a-constructor-or-a-function
adding elements of a vector of a base class
https://stackoverflow.com/questions/31410858/adding-elements-to-stdvector-of-an-abstract-class
can't access derived class method from pointer of base class - not entirely relavent, but good knowledge
https://stackoverflow.com/questions/23489554/cant-access-derived-class-method-from-pointer-of-type-base-class
I have created a shortened version of this problem in an example C++ executable that does not compile.
Here is the file:
/*
This script demonstrates my dilemma of trying to pass a subclass object
as a parameter to a function that expects the base class, and then
take that passed in object in the function and add it to a vector of that object
in a completely different class.
*/
#include <iostream>
#include <memory>
#include <vector>
class Baseclass
{
public:
Baseclass(int i)
{
lala = i;
}
// subclass MUST implement this method.
virtual int addme(int d) = 0;
protected:
int lala;
};
class Subclass : Baseclass
{
public:
Subclass(int d, int l) : Baseclass(d)
{
blahblah = l;
}
int addme(int d)
{
return blahblah + lala + d;
}
protected:
int blahblah;
};
class Mainclass
{
public:
Mainclass(uint blah)
{
anotherone = blah;
}
// This is the function I cannot seem to get to work.
// How can I make the function parameter an abstract class?
// The object being passed in is NOT abstract...
bool addController(Baseclass & basecont)
{
// This line here does NOT compile!!
// controllers.push_back(std::make_unique<What goes here?>(basecont));
return true;
}
protected:
uint anotherone;
std::vector<std::unique_ptr<Baseclass>> controllers;
};
int main(int argc , char ** argv)
{
// create subclassed controllers
Subclass cont1 = Subclass(12, 23);
Subclass cont2 = Subclass(233, 2);
// create main object
Mainclass mainbro = Mainclass(23);
// Add the subclased controllers to the main class
// THESE 2 lines do not compile!!
// mainbro.addController(cont1);
// mainbro.addController(cont2);
//
return 0;
}
I figure that I am doing something very wrong, but I do not feel the process I outlined in itself is impossible. I just think that I am going about the problem wrong.
I have highlighted, in the script, where I am not sure what I should do and where the code breaks.
I may need to take an alternative approach to the problem, I just do not know what alternatives I have available.
I see different way to fix your code, with different meaning.
Store pointers (main has ownership of the objects)
class Mainclass
{
public:
void addController(Baseclass& basecont)
{
controllers.push_back(&basecont);
}
protected:
std::vector<Baseclass*> controllers;
};
Transfer ownership
class Mainclass
{
public:
void addController(std::unique_ptr<Baseclass> basecont)
{
controllers.push_back(std::move(basecont));
}
protected:
std::vector<std::unique_ptr<Baseclass>> controllers;
};
with main:
int main()
{
auto cont1 = std::make_unique<Subclass>(12, 23);
auto cont2 = std::make_unique<Subclass>(233, 2);
Mainclass mainbro(23);
mainbro.addController(std::move(cont1));
mainbro.addController(std::move(cont2));
}
Store copies
class Mainclass
{
public:
void addController(Baseclass& basecont)
{
controllers.push_back(basecont.clone());
}
protected:
std::vector<std::unique_ptr<Baseclass>> controllers;
};
With
class Baseclass
{
// ...
public:
virtual int addme(int d) = 0;
virtual std::unique_ptr<Baseclass> clone() = 0;
};
class Subclass : Baseclass
{
// ...
public:
std::unique_ptr<Baseclass> clone() override { return std::make_unique<Subclass>(*this); }
};
Whenever you use base pointers or references with virtual methods, always add a virtual destructor:
virtual ~Baseclass() = default;
This prevents undefined behavior when the base pointers get deleted.
Next bit, use public inheritance to allow the compiler to implicitly upcast from unique_ptr<Subclass> to unique_ptr<Baseclass>:
class Subclass : public Baseclass
Your last issue is one of ownership. By having a vector of unique_ptr, you are saying that your class owns all those objects. But by declaring them on the stack in main you are saying that main owns them. Instead, use make_unique in the main routine, and transfer ownership with std::move:
bool addController(std::unique_ptr<Baseclass> basecont)
{
controllers.push_back(std::move(basecont));
return true;
}
...
auto cont1 = std::make_unique<Subclass>(12, 23);
auto cont2 = std::make_unique<Subclass>(233, 2);
// create main object
Mainclass mainbro = Mainclass(23);
mainbro.addController(std::move(cont1));
mainbro.addController(std::move(cont2));
All together:
#include <iostream>
#include <memory>
#include <vector>
class Baseclass
{
public:
Baseclass(int i)
{
lala = i;
}
virtual ~Baseclass() = default;
// subclass MUST implement this method.
virtual int addme(int d) = 0;
protected:
int lala;
};
class Subclass : public Baseclass
{
public:
Subclass(int d, int l) : Baseclass(d)
{
blahblah = l;
}
int addme(int d)
{
return blahblah + lala + d;
}
protected:
int blahblah;
};
class Mainclass
{
public:
Mainclass(uint blah)
{
anotherone = blah;
}
bool addController(std::unique_ptr<Baseclass> basecont)
{
controllers.push_back(std::move(basecont));
return true;
}
protected:
uint anotherone;
std::vector<std::unique_ptr<Baseclass>> controllers;
};
int main(int argc , char ** argv)
{
// create subclassed controllers
auto cont1 = std::make_unique<Subclass>(12, 23);
auto cont2 = std::make_unique<Subclass>(233, 2);
// create main object
Mainclass mainbro = Mainclass(23);
mainbro.addController(std::move(cont1));
mainbro.addController(std::move(cont2));
return 0;
}
Demo: https://godbolt.org/z/EyQD6S
#include <iostream>
#include <memory>
#include <vector>
class Baseclass
{
public:
Baseclass(int i)
{
lala = i;
}
// subclass MUST implement this method.
virtual int addme(int d) = 0;
protected:
int lala;
};
class Subclass : public Baseclass
{
public:
Subclass(int d, int l) : Baseclass(d)
{
blahblah = l;
}
int addme(int d)
{
return blahblah + lala + d;
}
protected:
int blahblah;
};
class Mainclass
{
public:
Mainclass(uint blah)
{
anotherone = blah;
}
// you need to make the function a template, otherwise
// you'll slice the top off the SubClass, and incorrectly
// make a copy of the base class (which you can't do,
// because BaseClass is pure virtual)
template<typename T>
bool addController(T& basecont)
{
// dont push_back new unique_ptrs, emplace_back instead!
controllers.emplace_back(new T(basecont));
return true;
}
protected:
uint anotherone;
std::vector<std::unique_ptr<Baseclass>> controllers;
};
int main(int argc , char ** argv)
{
// create subclassed controllers
Subclass cont1 = Subclass(12, 23);
Subclass cont2 = Subclass(233, 2);
// create main object
Mainclass mainbro = Mainclass(23);
// It's worth pointing out that these methods will take new copies of
// cont1 and cont2 (we don't want the mainbro instance to delete the
// memory for cont1 and cont2, since they are stack allocated)
mainbro.addController(cont1);
mainbro.addController(cont2);
//
return 0;
}
I have a class as follows:
Class A
{
virtual int doSomethingCool() = 0;
};
Class B : public A
{
int doSomethingCool();
};
Now the problem likes , I have a set of classes whcih are dependent on A as interface. I need to change the prototype of the function for one of the derived classes. i.e. i need to pass it a parameter.
Class C: public A
{
int doSomethingCool(int param);
};
Any suggestions how i can achieve this ?
No, you don't need to add it to the base class.
class A
{
public:
virtual int doSomethingCool() = 0 {}
};
class B : public A
{
public:
int doSomethingCool() {return 0;}
};
class C: public A
{
private:
int doSomethingCool(); // hide base class version!
public:
int doSomethingCool(int param) {return param;}
};
You can still call doSomethingCool() if done through a base class pointer:
C c;
//c.doSomethingCool (); // doesn't work, can't access private member
c.doSomethingCool (42);
A &a = c;
a.doSomethingCool ();
//a.doSomethingCool (42); // doesn't work, no member of A has that signature
Add it to the interface and default it to call the existing method. You don't have to do the default but don't make it pure otherwise all derived classes will have to implement. It might be better to leave it undefined or to throw. Depends on what you want to achieve.
class A
{
public:
virtual int doSomethingCool() = 0;
virtual int doSomethingCool(int param) {doSomethingCool()};
};
Make the function doSomethingCool() take the int parameter in A.
class A
{
public:
virtual void doSomethingCool(int param) = 0;
};
There's no problem. You can do it. The only caveat is that it will not be treated as an override of the base class virtual function.
class A
{
public:
virtual void doSomethingCool() = 0;
};
class B : public A
{
public:
void doSomethingCool();
};
class C: Public A
{
public:
void doSomethingCool(int param);
};
int main(){}
So while technically possible, you may really want to relook at the design of your interface class A.
One option may be to provide a default argument to A::doSomethingCool
virtual void doSomethingCool(int = 0) = 0;
This isn't syntactically correct C++.
No you can't change a prototype. How would it be used? What would be the value of the param if the non-parametric version would be called?
I would have introduced another, more specific, interface:
struct A
{
virtual int doSomethingCool() = 0;
};
struct A_specific : A
{
virtual int doSomethingCoolWithThis(int i) = 0;
};
class ConcreteA : public A
{
int doSomethingCool() { return 0; }
};
class ConcreteA_specific : public A_specific
{
int doSomethingCool() { return 0; }
int doSomethingCoolWithThis(int param) { return param; }
};
Then I would program to the correct interface:
int main()
{
const A& a1 = ConcreteA();
const A_specific& a2 = ConcreteA_specific();
a1.doSomethingCool();
a2.doSomethingCool();
a2.doSomethingCoolWithThis(2);
}
Just to give you another idea ;-)
Good luck!
I would to block child classes from overriding a base method and have the child classes override a new method in a parental class. In other words, a child class of the base class blocks the base class methods and delegates to a new method that further child classes must override. I still want the base class method to be available.
Here is an example:
#include <iostream>
#include <string>
struct Base
{
virtual const std::string& class_name(void) = 0;
};
struct Level1
: public Base
{
private: // Prevent child classes from overriding
// the Base::class_name method
const std::string& class_name(void)
{
static std::string name;
name = "class" + class_name_from_level_1();
return name;
}
protected:
// This is the "new" or redirected class that child classes
// must override.
virtual const std::string& class_name_from_level_1(void) = 0;
};
struct Level2
: public Level1
{
static std::string name;
const std::string& class_name_from_level_1(void)
{
if (name.length() == 0)
{
name = "Level2";
}
return name;
}
};
int main(void)
{
Level2 lev2;
std::cout << lev2.class_name() << "\n";
return 0;
}
I am getting the following errors from g++:
$ g++ hiding_virt_methods.cpp -o hiding_virt_methods.exe
hiding_virt_methods.cpp: In function `int main()':
hiding_virt_methods.cpp:15: error: `virtual const std::string& Level1::class_name()' is private
hiding_virt_methods.cpp:43: error: within this context
In the above example, I want the following chain of execution for Level2:
Base::class_name() --> Level1::class_name_from_level_1() --> Level2::class_name_from_level_1()
Also, I only want to block inheritance of specific methods in the Base class. Protected and Private Inheritance affect all the public methods.
So how do I stop the chain of inheritance of specific Base methods at different levels in the inheritance tree?
Edit: Real world example.
I have an interface class Record. Class Record_With_Id inherits from class Record and adds an ID field. The class Record contains an accept_visitor method. Class Record_With_Id overrides accept_visitor to apply to the ID field, then calls a virtual method, record_with_id_accept_visitor, which descendants must implement.
For your immediate problem, you can rename your class_name() functions to class_name_impl() or similar, then in the base class have a class_name() function that calls the implementation one. That way, only the base class version will match when calling class_name() on a derived object.
More generally, you can frustrate attempts to call the base class methods by having same-named functions in the derived classes - as you've done, but anyone can cast to a Base& and call whatever they like. You can't stop virtual methods being overridable in derived classes... you can only frustrate their use.
It's worth remembering that a publicly derived class IS an instance of the base class, and SHOULD provide the base class's interface.
EDIT: re yout "real world example" edit, can you explain the problem with a normal implementation ala...
#include <iostream>
struct Visitor
{
virtual void operator()(int&) const = 0;
};
struct X
{
virtual void visit(Visitor& v) { v(a); v(b); }
int a;
int b;
};
struct X_with_C : X
{
int c;
virtual void visit(Visitor& v) { X::visit(v); v(c); }
};
struct My_Visitor : Visitor
{
void operator()(int& n) const { std::cout << ++n << '\n'; }
};
int main()
{
X x;
x.a = 10;
x.b = 20;
My_Visitor visitor;
x.visit(visitor);
X_with_C xc;
xc.a = -10;
xc.b = -20;
xc.c = -30;
xc.visit(visitor);
X& rx = xc;
rx.visit(visitor);
}
Output:
11
21
-9
-19
-29
-8
-18
-28
hasn't C++11 added final and override?
http://en.wikipedia.org/wiki/C%2B%2B11#Explicit_overrides_and_final
Four years later, let me add that C++11 has introduced keyword final:
class Base final {
This can also be applied on the virtual methods:
class Base{
protected:
virtual void doWork() = 0;
public:
virtual void startWork() final { doWork(); }
};
class Derived: public Base{
protected:
virtual void doWork() override { /* some work */ }
public:
// error: overriding final function ‘virtual void Base::startWork()’
virtual void startWork() override { /* something else */ }
};
Visual Studio 2005 and above implement a keyword "sealed", which is a Microsoft extension to C++. You put it in the declaration of Level1::class_name(). I don't think there is a portable way.
It appears that you're trying to do something in a way that's hard.
Depending on what it is that you're trying to achieve, the following may be a solution.
#include <iostream>
#include <string>
struct Base
{
virtual std::string class_name() const = 0;
};
class Level1
: public Base
{
public:
std::string class_description() const
{
return "class " + class_name();
}
};
class Level2
: public Level1
{
public:
virtual std::string class_name() const
{
return "Level2";
}
};
int main()
{
Level2 lev2;
std::cout << lev2.class_description() << "\n";
}
In the above code I've assumed it's for debugging/tracing or something like that. For id purposes look into typeid (a built-in operator).
Cheers & hth.,