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.
Related
How to read the following code for main?
I do not know this
Code :
class one
{
public:
void operator()() const
{
f();
f1();
}
};
I want to call the operator To main?
void operator()() const defines a function call operator, which can be used as:
one ob;
ob(); // calls ob.operator()()
For another, more complete, example.
#include <iostream>
class Two
{
public:
int operator()(const char *str) const
{
std::cout << "operator() called with " << str << std::endl;
return 101;
}
};
int main()
{
Two two;
int n = two("'test'");
std::cout << "operator() returned " << n << std::endl;
}
Output:
operator() called with 'test'
operator() returned 101
You can create an instance of the class in the main function and call the function using that instance.
class one
{
public:
void operator()() const
{
f();
f1();
}
};
int main() {
one obj_one;
// calling the member function -> method
obj_one.operator()();
return 0;
}
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("");
}
Consider the following program
class A {};
class B : public A {};
void fun(A v) { std::cout << "A" << std::endl; }
void fun(B v) { std::cout << "B" << std::endl; }
void call(A v) { fun(v); }
int main(int argc, char *argv[]) {
A a;
B b;
call(a);
call(b);
fun(a);
fun(b);
}
It will print
A
A
A
B
Is there a way for the program to notice that the variable is actually a B in the second case, and hence call the overloaded fun(B), so that the output would become the following instead?
A
B
A
B
Option 1
You could use a template for your call function.
#include <iostream>
class A {};
class B : public A {};
void fun(A v) { std::cout << "A" << std::endl; }
void fun(B v) { std::cout << "B" << std::endl; }
template <typename T>
void call(T v) { fun(v); }
int main(int argc, char *argv[]) {
A a;
B b;
call(a);
call(b);
fun(a);
fun(b);
}
This will only compile if there is an overload of fun that takes a parameter of type T, which in your case is A or B.
Working example
Option 2
Alternatively, you could make these free functions into virtual class methods and actually use polymorphism.
#include <iostream>
class A
{
public:
virtual void fun() { std::cout << "A" << std::endl; }
void call() { fun(); }
};
class B : public A
{
public:
virtual void fun() override { std::cout << "B" << std::endl; }
};
int main(int argc, char *argv[]) {
A a;
B b;
a.call();
b.call();
a.fun();
b.fun();
}
Working example
Is there a reason you don't want fun to be part of the classes? If fun was a virtual method on the class, and call took an A and simply did v.fun() it would find the proper implementation to execute
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);
}