I have three classes that each inherit from the other: A is inherited by B is inherited by C. I also have one virtual function in each of these classes. I want to create an A-class pointer holding a C-class object and call the B-class function like so:
class A
{
public:
virtual void doStuff() = 0;
};
class B : public A
{
public:
virtual void doStuff() override;
};
class C : public B
{
public:
void doStuff() override;
};
void B::doStuff()
{
std::cout << "Starting doStuff in B\n";
doStuff();
std::cout << "Ending doStuff in B\n";
}
void C::doStuff()
{
std::cout << "doStuff in C\n";
}
int main()
{
A *pointer = new C();
pointer->B::doStuff(); // This doesn't work
}
If I change my main slightly, I get the correct output:
int main()
{
B *pointer = new C(); // Changed A to B
pointer->B::doStuff();
}
Output
Starting doStuff in B
doStuff in C
Ending doStuff in B
How can I change my original code to use an A-class pointer and preferably only one function name?
The issue is that B::doStuff, which refers to the implementation of doStuff at class B, is not a member of A. If you are sure that the pointer is actually pointing to an instance of B or something derived from B, then you could write the following:
int main()
{
A *pointer = new C();
reinterpret_cast<B*>(pointer)->B::doStuff(); // This should work
}
If you cannot be sure about the instance type, use a dynamic_cast.
A pointer of type A can't know for certain that the B version of doStuff is accessible by default; you need to cast the pointer first.
int main()
{
A *pointer = new C();
if(B *b_ptr = dynamic_cast<B*>(pointer))
b_ptr->B::doStuff(); //Will only be executed if dynamic_cast was successful
}
Also, if you're going to use polymorphism like this, make sure you make A's destructor virtual as well, or cleanup won't behave.
class A
{
public:
virtual void doStuff() = 0;
virtual ~A() noexcept = default;
};
Here is some sample code to show why I want to do this. This code will output syntax similar to XML. Calling the "middle" class's function allows me to surround any derived class with the correct "IdentifiedRegion" tags.
#include <iostream>
#include <string>
#include <vector>
class Region
{
public:
virtual void doStuff(std::string tabs) = 0;
};
class IdentifiedRegion : public Region
{
public:
virtual void doStuff(std::string tabs) override;
};
class CircularRegion : public Region
{
public:
CircularRegion(int latitudeIn, int longitudeIn, int radiusIn) : latitude(latitudeIn), longitude(longitudeIn), radius(radiusIn) {}
void doStuff(std::string tabs) override;
private:
int latitude;
int longitude;
int radius;
};
class CountryRegion : public IdentifiedRegion
{
public:
CountryRegion(int countryCodeIn) : countryCode(countryCodeIn) {}
void doStuff(std::string tabs) override;
private:
int countryCode;
};
class StateRegion : public IdentifiedRegion
{
public:
void doStuff(std::string tabs) override;
StateRegion(std::string abbreviationIn) : abbreviation(abbreviationIn) {}
private:
std::string abbreviation;
};
void IdentifiedRegion::doStuff(std::string tabs)
{
std::cout << tabs << "<IdentifiedRegion>\n";
doStuff(tabs + "\t");
std::cout << tabs << "</IndentifiedRegion>\n";
}
void CircularRegion::doStuff(std::string tabs)
{
std::cout << tabs << "<CircularRegion>\n";
std::cout << tabs << "\t" << "<latitude>" << latitude << "</latitude>\n";
std::cout << tabs << "\t" << "<longitude>" << longitude << "</longitude>\n";
std::cout << tabs << "\t" << "<radius>" << radius << "</radius>\n";
std::cout << tabs << "</CircularRegion>\n";
}
void CountryRegion::doStuff(std::string tabs)
{
std::cout << tabs << "<CountryRegion>\n";
std::cout << tabs << "\t" << "CountryCode>" << std::to_string(countryCode) << "</CountryCode>\n";
std::cout << tabs << "</CountryRegion>\n";
}
void StateRegion::doStuff(std::string tabs)
{
std::cout << tabs << "<StateRegion>\n";
std::cout << tabs << "\t" << "<Abbreviation>" << abbreviation << "</Abbreviation>\n";
std::cout << tabs << "</StateRegion>\n";
}
int main()
{
Region *country = new CountryRegion(12);
Region *state = new StateRegion("WA");
Region *radius = new CircularRegion(10, 20, 30);
reinterpret_cast<IdentifiedRegion*>(country)->IdentifiedRegion::doStuff("");
reinterpret_cast<IdentifiedRegion*>(state)->IdentifiedRegion::doStuff("");
radius->doStuff("");
}
Related
I guess i am having some trouble in understanding dynamic bynding.
Suppose we are having 2 classes:
class a1{ //..
virtual void print() const;
};
class a2:a1{ //...
void print() const override;
};
Why is the following true:
a2 item_son;
a1 &item_father = item_son;
item_father->print();
the print called is the one of the son.
Actually, the OP did realize the meaning of virtual overloading vs. non-virtual overloading of functions. However, I got my sample running, hence, I'd like to publish it:
#include <iostream>
class A1 {
public:
virtual void print() const
{
std::cout << "A1::print() called." << std::endl;
}
};
class A2: public A1 {
public:
void print() const override
{
std::cout << "A2::print() called." << std::endl;
}
};
class B1 {
public:
void print() const
{
std::cout << "B1::print() called." << std::endl;
}
};
class B2: public B1 {
public:
void print() const
{
std::cout << "B2::print() called." << std::endl;
}
};
using namespace std;
int main(void)
{
A2 a2;
cout << "Calling a2.print(): ";
a2.print();
A1 &a1 = a2;
cout << "Calling a1.print(): ";
a1.print();
B2 b2;
cout << "Calling b2.print(): ";
b2.print();
B1 &b1 = b2;
cout << "Calling b1.print(): ";
b1.print();
return 0;
}
Output:
Calling a2.print(): A2::print() called.
Calling a1.print(): A2::print() called.
Calling b2.print(): B2::print() called.
Calling b1.print(): B1::print() called.
Life demo on ideone
digging some codes, I found a curiously manner to call a method from an instance object which I will show in the example code bellow:
class Example{
public:
void Print(){ std::cout << "Hello World" << std::endl;}
};
int main(){
Example ex;
ex.Example::Print(); // Why use this notation instead of just ex.Print();
return 0;
}
There is any behaviour difference between ex.Example::Print() and the standard way ex.Print()? Why the author' code used the former instead of the latter?
Thanks in advance
The difference is that ex.Example::Print() specifies that you want the version of Print() defined in the class Example. In this particular example, there's no difference. However, consider the following:
#include <iostream>
class One {
int i;
public:
One(int ii) : i(ii) {}
virtual void print() { std::cout << i << std::endl; }
};
class Two : public One {
int j;
public:
Two(int ii, int jj) : One(ii), j(jj) {}
void print() override {
One::print();
std::cout << j << std::endl;
}
};
class Three : public Two {
int k;
public:
Three(int ii, int jj, int kk) : Two(ii, jj), k(kk) {}
void print() override {
Two::print();
std::cout << k << std::endl;
}
};
int main() {
Three four(1, 2, 3);
four.print();
std::cout << std::endl;
four.One::print();
std::cout << std::endl;
four.Two::print();
std::cout << std::endl;
four.Three::print();
std::cout << std::endl;
}
The output will be:
1
2
3
1
1
2
1
2
3
ex.Example::Print(); // Why use this notation instead of just ex.Print();
Given the posted code, that is the same as:
ex.Print();
It will make a difference only if name hiding comes into play and you want to be explicit about calling a particular version of the function.
Ex:
struct Foo
{
void Print() const { std::cout << "Came to Foo::Print()\n"; }
};
struct Bar : Foo
{
void Print() const { std::cout << "Came to Bar::Print()\n"; }
};
int main()
{
Bar b;
b.Print(); // Calls Bar::Print()
b.Foo::Print(); // Calls Foo::Print()
}
That's just the mechanics of how things work. As a design choice, it will be better to use virtual functions:
struct Foo
{
virtual void Print() const { std::cout << "Came to Foo::Print()\n"; }
};
struct Bar : Foo
{
virtual void Print() const { std::cout << "Came to Bar::Print()\n"; }
};
No difference between calling ex.Example::Print() and ex.Print() in this example.
The only use/benefit of this invocation I can think of is with inheritance; You can explicitly call over-ridden method in parent class using this syntax from an instance of derived class.
Lets say I have implemented the following classes
class A
{
public:
virtual void printA()
{
cout << "Hi from A!" << endl;
}
};
class B : public A
{
public:
virtual void printB()
{
cout << "Hi from B!" << endl;
}
};
class C : public B
{
public:
void printC()
{
cout << "Hi from C!" << endl;
}
};
Lets also say I have created a std::vector<A *> vec that contains random amount of objects instantiated from A, B, and C. Now lets say I am forced to iterate through all the objects in vec but only call objects that have the printC() method (i.e C instances). What is the best way to do this?
int main()
{
std::vector<A *> vec;
....
// insert random objects from both A, B and C into vec
....
for(vector<A *>::iterator x = vec.begin();
x != vec.end();
x++)
{
if(dynamic_cast<C *>(*x) != 0) // 1. is this OK?
(*x)->printC();
else
(*x)->printA(); // 2. is this also OK?
}
}
Is 1 Ok? And if so is this the best practice?
Also will 2 cause problems in the case of C instances?
Maybe these are stupid questions, but Im quite new to C++ and how polymorphism works in C++ is very strange to me. Thanks
I think you mean the following
#include <iostream>
#include <vector>
int main()
{
class A
{
public:
virtual ~A() = default;
virtual void print() const
{
std::cout << "Hi from A!" << std::endl;
}
};
class B : public A
{
public:
void print() const
{
std::cout << "Hi from B!" << std::endl;
}
};
class C : public B
{
public:
void print() const
{
std::cout << "Hi from C!" << std::endl;
}
};
std::vector<A *> v = { new A(), new B(), new C() };
for ( A *p : v ) p->print();
return 0;
}
The output is
Hi from A!
Hi from B!
Hi from C!
1 won't work, since *x has type A*, and A doesn't have a printC member. It should be:
if (C * c = dynamic_cast<C *>(*x)) {
c->printC();
}
2 is fine, but doesn't match your description; you say you want to "only call objects that have the printC() method", while this calls printA() on the other objects.
This does seem like an odd design though; you'd usually define a single virtual function, implemented by each class to do the right thing for that class, then call that unconditionally for everything.
It's hard to explain exactly what I want to do here, but I have a base class and two classes which inherit this base class. Both classes which inherit it have their own unique members. I want to be able to pass both to a method, and have that method detect which it is, then access their unique members. I can't assume there will only be two classes which inherit it, so i'm looking for something of a more general solution.
Here is an example of what I'd like to do:
#include <iostream>
class Base {
public:
int _type;
Base() { }
};
class First : public Base {
public:
int _first_only;
First() { }
};
class Second : public Base {
public:
int _second_only;
Second() { }
};
void test (Base b) {
std::cout << "Type: " << b._type << std::endl;
if(b._type==1) {
std::cout << "First\n";
// Want to be able to do this
std::cout << "Val: " << (First)b._first_only << std::endl;
} else if(b._type==2) {
std::cout << "Second\n";
// And this
std::cout << "Val: " << (Second)b._second_only << std::endl;
}
}
int main() {
First f;
f._first_only=1;
f._type=1;
Second s;
s._type=2;
s._second_only=2;
test(f);
test(s);
}
This is similar to others answers:
You can write polymorphic classes to get this behavior using virtual functions.
Pass the Dervied class objects either by pointer or by reference to get polymorphic behaviour. Otherwise it will lead to object slicing. Your test() function leads to object slicing.
This code may also help you. You can see that there are different ways to print the type. I used GetBaseType(), GetDerivedType() and GetType(). Among these GetType() method is convenient for you case. There are two constructors for convenience. Constructors allow to initialize data members.
class Base {
private:
int _type;
public:
Base(int type) : _type(type) { }
int GetBaseType() { return _type; }
virtual int GetDerivedType() = 0;
virtual int GetType() { return _type; }
};
class First : public Base {
private:
int _first_only;
public:
First() : Base(1), _first_only(1) { }
First(int first_only) : Base(first_only), _first_only(first_only) { }
int GetDerivedType() { return _first_only; }
virtual int GetType() { return _first_only; }
};
class Second : public Base {
private:
int _second_only;
public:
Second() : Base(2), _second_only(2) { }
Second(int second_only) : Base(second_only), _second_only(second_only) { }
int GetDerivedType() { return _second_only; }
virtual int GetType() { return _second_only; }
};
void test (Base &b) {
std::cout << "Type: " << b.GetBaseType() << std::endl;
std::cout << "Type: " << b.Base::GetType() << std::endl;
std::cout << "Dervied type: \n";
std::cout << "Val: " << b.GetDerivedType() << std::endl;
std::cout << "Val: " << b.GetType() << std::endl;
}
int main() {
First f(1);
Second s(2);
test(f);
test(s);
First f1;
Second s1;
test(f1);
test(s1);
}
Either declare a virtual function in Base
Move the common members types from First and Second into Base.
For your specific problem, 2nd option is better:
class Base {
public:
int _member; // have getter() method, if '_member' is private
Base() { }
};
Inside, test():
void test (Base &b) { // <--- practice to pass by reference if copy is not needed
// use b._member;
};
Your code does not work polymorphically, because you are passing the function-parameter by value, which results in slicing.
If you have a method that does different things for different types, consider overloading it for each of these types.
Three things I'd do:
In general switching on type codes is not considered good object oriented design: Instead pull the switched code into the classes.
I'd also set up the type tags in the constructor of the specific classes.
And as others have mentioned you need to pass the argument by reference to avoid slicing.
Here's what the code would look like:
#include <iostream>
class Base {
public:
int _type;
Base() { }
virtual void print_to_stream( std::ostream & os ) const =0;
};
class First : public Base {
public:
int _first_only;
First() { _type =1; }
void print_to_stream( std::ostream & os ) const
{
os<<"First\n";
os<<"Val: " << _first_only << std::endl;
}
};
class Second : public Base {
public:
int _second_only;
Second() { _type=2; }
void print_to_stream( std::ostream & os ) const
{
os << "Second\n";
os << "Val: " << _second_only << std::endl;
}
};
void test (Base & b)
{
std::cout << "Type: " << b._type << std::endl;
b.print_to_stream( std::cout );
}
int main() {
First f;
f._first_only=1;
Second s;
s._second_only=2;
test(f);
test(s);
}
I have an existing application in C++ with a custom ArrayBase class that manages storage and access to a contiguously allocated region of memory. I have a separate ItrBase class that is used to access data in that ArrayBase. ArrayBase has a createItr() function that currently returns an ItrBase object.
I need to extend ArrayBase to use multiple memory allocations instead of one contiguous one. I have created an EnhancedArray class to do that. For this EnhancedArray to be compatible with the existing application, it's createItr() function must return something that works with the new multiple memory allocations.
So, I have created a derived EnhanceItr class to do this.
My problem is I can't figure out a way for hundreds of code occurrences like this:
ItrBase anIterator = anArray.createItr();
...
double x = anIterator.getData();
to use the EhancedItr's getData() function when anArray is an EnhancedArray.
Here is a simple application illustrating my basic arrangement.
#include <iostream>
using namespace std;
class ItrBase {
public:
ItrBase() { cout << "ItrBase constructor.\n"; };
~ItrBase() { cout << "ItrBase destructor.\n"; };
virtual int vfunc() {return 1;};
};
class EnhancedItr : public ItrBase {
public:
EnhancedItr() { cout << "EnhancedItr constructor.\n"; };
~EnhancedItr() { cout << "EnhancedItr destructor.\n"; };
int vfunc() {return 0;};
};
class ArrayBase {
public:
ArrayBase() { cout << "ArrayBase constructor.\n"; };
~ArrayBase() { cout << "ArrayBase destructor.\n"; };
virtual ItrBase & createItr() {cout << "in AB's createItr()\n"; return *new ItrBase(); };
};
class EnhancedArray : public ArrayBase {
public:
EnhancedArray() { cout << "EnhancedArray constructor.\n"; };
~EnhancedArray() { cout << "EnhancedArray destructor.\n"; };
EnhancedItr & createItr() {cout << "in EA's createItr()\n"; return *new EnhancedItr(); };
};
int main()
{
ArrayBase ab;
EnhancedArray ea;
ItrBase itr = ab.createItr();
ItrBase eitr = ea.createItr(); //EnhancedItr assigned to ItrBase
cout << "ArrayBase's Itr .vfunc(): " << itr.vfunc() <<std::endl;
cout << "EnhancedArray's Itr .vfunc(): " << eitr.vfunc() <<std::endl;
return 0;
}
Both calls to vfunc() above return 1, when I want the second call to return 0.
In main(), I know that if I change the ItrBase types to ItrBase &'s, I do get the desired return types, but then I am modifying my 'existing' code in hundreds of areas, and the destructors for the Iterators are not called.
Is there another strategy that I am not seeing?
Thanks.
Sure, if you're allowed to rewrite ItrBase, then you can use delegation to pass all function calls through to an implementation class, which you hold by pointer or reference so that polymorphism is in effect. This would look a lot like pimpl. And the callers would not have to be written at all, only recompiled.
EDIT: code for those not familiar with pimpl.
struct ItrBase
{
struct ItrImpl
{
virtual ~ItrImpl(){}
virtual int vfunc() = 0;
};
ItrBase(ItrImpl peer) : m_peer(peer) { cout << "ItrBase constructor.\n"; }
~ItrBase() { cout << "ItrBase destructor.\n"; }
int vfunc() { return m_peer->vfunc(); }
private:
const unique_ptr<ItrImpl> m_peer;
};
class ArrayBase
{
struct ItrImpl : public ItrBase::ItrImpl
{
virtual int vfunc() { return 0; }
};
public:
ArrayBase() { cout << "ArrayBase constructor.\n"; };
~ArrayBase() { cout << "ArrayBase destructor.\n"; };
virtual ItrBase createItr() { cout << "in AB's createItr()\n"; return ItrBase(new ItrImpl); };
};
class EnhancedArray : public ArrayBase
{
struct ItrImpl : public ItrBase::ItrImpl
{
virtual int vfunc() { return 1; }
};
public:
EnhancedArray() { cout << "EnhancedArray constructor.\n"; };
~EnhancedArray() { cout << "EnhancedArray destructor.\n"; };
virtual ItrBase createItr() { cout << "in EA's createItr()\n"; return ItrBase(new ItrImpl); };
};
You're running into a problem called slicing: createItr returns a reference, and then you're copying that into an ItrBase by-value. It's as if you did something like this:
EnhancedItr itr1 = ...;
BaseItr itr2 = itr1; // copy by-value
cout << itr2.vfunc(); // prints 1, not 0
You're also leaking memory: createItr returns a newly allocated object, but you're never deleting it. This is very bad, especially since you'd expect array iterators to be used frequently.
completely different thing you can do is use,
BOOST_AUTO(iterator, array);
and let compiler figure out return type.
BOOST_AUTO
Not being up-to-date with the Standard Library, I could not use the unique_ptr<> implementation suggested by Ben Voigt. (version >=4.3) I believe I have taken his concept and implemented it with basic pointers instead. Noting, however, that this implementation is not exception-safe. ItrImpl objects could be left undeleted.
Here's my code. Too bad createItr() has to return a ItrBase object rather than a pointer, otherwise I think I could have gotten auto_ptr<> to work. Output during program execution shows that ~ItrBase() is called only once for each instance, but I am suprised it is not called also during the object return from createItr(). Return value optimization?
#include <iostream>
using namespace std;
struct ItrBase
{
struct ItrImpl
{
virtual ~ItrImpl(){};
virtual int vfunc() const = 0;
};
ItrBase(ItrImpl* peer) : m_peer(peer) { cout << "ItrBase constructor.\n"; };
~ItrBase() { cout << "ItrBase destructor. \n"; delete m_peer; };
int getData() const { return m_peer->vfunc(); };
private:
ItrImpl* const m_peer;
};
class ArrayBase
{
struct ItrImpl : public ItrBase::ItrImpl
{
virtual int vfunc() const { return 0; };
};
public:
ArrayBase() { cout << "ArrayBase constructor.\n"; };
~ArrayBase() { cout << "ArrayBase destructor.\n"; };
virtual ItrBase createItr() { cout << "in AB's createItr()\n"; return ItrBase(new ItrImpl); };
};
class EnhancedArray : public ArrayBase
{
struct ItrImpl : public ItrBase::ItrImpl
{
virtual int vfunc() const { return 1; };
};
public:
EnhancedArray() { cout << "EnhancedArray constructor.\n"; };
~EnhancedArray() { cout << "EnhancedArray destructor.\n"; };
virtual ItrBase createItr() { cout << "in EA's createItr()\n"; return ItrBase(new ItrImpl); };
};
int main()
{
ArrayBase ab;
EnhancedArray ea;
ItrBase itr = ab.createItr();
ItrBase eitr = ea.createItr(); //EnhancedItr assigned to ItrBase
cout << "ArrayBase's Itr .vfunc(): " << itr.getData() <<std::endl;
cout << "EnhancedArray's Itr .vfunc(): " << eitr.getData() <<std::endl;
return 0;
}