Must I need to redefine all the overloading operators with derived type if I require to use them in derived class?
The following code compiles fine:
class Point {
public:
Point(int X = 0, int Y = 0):x(X), y(Y) {}
virtual ~Point() {}
Point operator +(Point &rhs) {
return Point(x + rhs.x, y + rhs.y);
}
protected:
int x, y;
};
class Vector : public Point {
public:
Vector(int X, int Y) : Point(X, Y) {}
~Vector() {}
Vector operator +(Vector &rhs) {
return Vector(x + rhs.x, y + rhs.y);
}
};
int main()
{
Vector v1(1, 2);
Vector v2(3, 2);
Vector v3 = v2 + v1;
}
But from what I've read,
C++ Primer 4th Ed. Section 15.5.3.
If a derived class wants to make all the overloaded versions available through its type, then it must either redefine all of them or none of them.
Does the part of the quote "none of them" make any sense here?
What it means is that if Point had more than one operator+(), and you only redefined one of them, then only that one would be accessible in the derived class; the other overloads would be hidden. If you declare no operator+() in the derived class, then all of the parent ones are available; if you declare any in the derived class, then none of the parent ones are available.
Make sense? This case is fine: the parent declares one, and you redefine that one. No problems. If the parent declared two, though, then your child class, which only declares one, would only have access to that one.
Overloading operators in derived class from IBM.
A member function named f in a class A
will hide all other members named f in
the base classes of A, regardless of
return types or arguments. The
following example demonstrates this:
struct A {
void f() { }
};
struct B : A {
void f(int) { }
};
int main() {
B obj_B;
obj_B.f(3);
// obj_B.f();
}
The compiler would not allow the
function call obj_B.f() because the
declaration of void B::f(int) has
hidden A::f().
To overload, rather than hide, a
function of a base class A in a
derived class B, you introduce the
name of the function into the scope of
B with a using declaration. The
following example is the same as the
previous example except for the using
declaration using A::f:
struct A {
void f() { }
};
struct B : A {
using A::f;
void f(int) { }
};
int main() {
B obj_B;
obj_B.f(3);
obj_B.f();
}
So if you do not overload all of them, then only the overloaded functions will be used.
In C++, there is no overloading across scopes derived class scopes are not an exception to this general rule.
There is no overload resolution between Derived and Base class. An example:
class B
{
public:
int func1(int i)
{
cout<<"B::func1()";
return i+1;
}
};
class D : public B
{
public:
double func1(double d)
{
cout<<"D::func1()";
return d+1.3;
}
};
int main ()
{
D *pd = new D;
cout << pd->func1(2) <<endl;
cout << pd->func1(2.3)<<endl;
return 0;
}
The output is:
D::func1()3.3
D::func1()3.6
This same rule applies for operator member functions as well, after all they are member functions too!
So in your code example if Point had more than one operator+(), and you redefined the same operator in Derived class then only that derived class operator will be accessible to objects of derived class because that version of the function hides the other Base class versions of operator+().
If you do not redefine the operator+() in the derived class, then none of the parent class versions of the operator+() are hidden and hence accessible through objects of Derived class.
Hence the statement:
If a derived class wants to make all the overloaded versions available through its type, then it must either redefine all of them or none of them.
Also, please note that overloading, overriding and function hiding are three terms that are loosely mis-used interchangeably sometimes but they all have separate meanings.
Related
I have a task to implement a simple SVG generator. I need to support Circle, Polyline and Text. All three have at least 4 common methods:
- SetStrokeColor
- SetFillColor
- SetStrokeWidth
- ToString
One of the main requirements is to support chaining, e.g.:
Polyline{}.SetStrokeColor("white").SetFillColor("black")...
I decided to implement a base class Element, which all the other classes inherit from. The idea is to have a class Document that holds a vector of all the elements added to the document.
A sample signature for a base method:
// source of trouble
Element &SetStrokeColor(const Color &color) {
...
return *this;
}
My derived classes do call these methods, but the trouble is that the methods return a reference to the base class Element, not the derived class.
My question is whether it is all together possible to implement in c++???
Further discussion here
If you want to share implementations and preserve type information, the CRTP is what you need:
struct ElementBase { };
template <class Concrete>
struct Element : ElementBase {
Concrete &setStrokeWidth(int width) {
// Actual implementation...
(void) width;
return cthis();
}
private:
friend Concrete;
Element() = default;
Concrete &cthis() { return static_cast<Concrete &>(*this); }
Concrete &cthis() const { return static_cast<Concrete const &>(*this); }
};
struct Circle : Element<Circle> {
Circle &SetCircleCenter(int x, int y) {
// Actual implementation...
(void) x;
(void) y;
return *this;
}
};
int main() {
Circle c;
c.setStrokeWidth(4).SetCircleCenter(0, 0);
}
See it live on Wandbox
With covariant return types, you can
class Element {
public:
// ...
virtual Element& refToThis() { return *this; };
};
and in derived classes
class Derived : public Element {
public:
// ...
Derived& refToThis() override { return *this; };
};
which lets you handle Derived instances as Derived instances when the static type is Derived (e.g. inside Derived itself). When tht static type is Element, the return type of refToThis() is, too.
For comparison:
class Base {};
class Derived : public Base {};
Derived d;
Base* p = &d; // points to a Base that in reality is a derived
Base& b = d; // in this respect, references do not differ...
// and you can get the original type back:
auto dr = static_cast<Derived&>(b); // if you know 100% for sure that b is a Derived
auto dp = dynamic_cast<Derived*>(p); // if p might point to another type; you get
// a null pointer back, if it does
There is absolutely no difference with returning pointers or references to this/*this, so yes, you can safely do so.
Edit:
Circle().SetStrokeWidth(16).SetCircleCenter({0, 0}). SetStrokeWidth returns a reference to Element, so SetCircleCenter is unavailable.
In this case, you are a bit in trouble, though. As lubgr denoted already, you can solve the issue by overriding with co-variant return type – and yes, this would mean that you'd have to override each function separately. Alternatively, you can save all this approach using CRTP:
template <typename T>
class SomeAppropriateName : public Element
{
public:
T& setStrokeWidth(unsigned int width)
{
Element::setStrokeWidth(width);
return static_cast<T&>(*this);
}
};
class Circle : public SomeAppropriateName<Circle>
{
// the overrides needed are inherited...
};
For this approach, original functions from Element class needs to be non-virtual (actually an advantage, as virtual function calls are more costly...); in the template, the argument (T, i. e. Circle) is not yet completely defined (with CRTP pattern) and the compiler wouldn't be able to check if the return type really is co-variant. So actually, we are just shadowing the base class' function.
This is still no disadvantage compared to overriding: The co-variant return type will only be available if the (virtual) function is called on the object directly anyway:
Circle c;
c.setStrokeWidth(7).setCenter();
Element& e = c;
e.setStrokeWidth(7).setCenter(); // fails, even if you implement co-variant override directly
It's a fact that you can explicitly access member variables (inside a member function, and not particularly a constructor) using this syntax : this->member_name (i.e. to distinguish with a function argument with the same name).
Besides this, I thought that the syntax ClassName::static_member was reserved to access static members outside of a class.
Then I was surprised when I realized that the following set_2() method was working as one could expect:
#include <iostream>
struct A {
int x;
// The two following methods seem to act similarly:
void set_1(int x) { this->x = x; }
void set_2(int x) { A::x = x; }
};
int main ()
{
A a;
a.set_1(13);
std::cout << a.x << std::endl;
a.set_2(17);
std::cout << a.x << std::endl;
return 0;
}
Output:
13
17
Is is a good and valid practice to use the scope operator (A::x) in this case? I would personnally prefer it, instead of using the this->x syntax.
Using A::x in this case is valid, but I think this->x is more idiomatic and less error-prone (the reader of the code can immediately see that x is a member of the class, without thinking what A is).
According to the C++ Standard (3.3.7 Class scope)
2 The name of a class member shall only be used as follows:
— in the scope of its class (as described above) or a class derived
(Clause 10) from its class,
— after the . operator applied to an expression of the type of its
class (5.2.5) or a class derived from its class,
— after the -> operator applied to a pointer to an object of its class
(5.2.5) or a class derived from its class,
— after the :: scope resolution operator (5.1) applied to the name of
its class or a class derived from its class.
For example data members of methods of a derived class can hide data members and/or methods of its base class. To access data members and nethods of the base class you can use the scope resolution operator.
struct Base
{
virtual ~Base() {};
virtual void Hello() const { std::cout << "Base" << std::endl; }
};
struct Derived : Base
{
virtual void Hello() const
{
Base::Hello();
std::cout << "and Derived" << std::endl;
}
};
Derived d;
d.Hello();
The A::x, in your case, still refers to your regular member variable; it just explicitly specifies which x you mean. Consider a class that derives from two other classes which have a member of the same name (not that that's very good coding style):
struct A { int x; };
struct B { int x; };
struct C : A, B
{
int foo() const
{
// return x; // ambiguous: which x do you mean?
return A::x; // unambiguous
}
};
I wonder why people say:
"Inheriting class doesn't inherit the constructor".
If you could CAN use the parent class' constructor, and the parameterless constructor are called automatically no matter what.
Example:
#include <iostream>
using namespace std;
class A {
private :
int x;
public :
A () {
cout << "I anyway use parameter-less constructors, they are called always" << endl;
}
A (const int& x) {
this->x = x;
cout << "I can use the parent constructor" << endl;
}
};
class B : public A {
private :
int y;
public :
B() {
}
B (const int& x, const int& y) : A (x) {
this->y = y;
}
};
int main() {
B* b = new B(1,2);
B* b1 = new B();
return 0;
}
http://ideone.com/e.js/6jzkiP
So is it correct to 'say', constructors are inherited in c++ ? What is exact definition of "inherit" in programming languages ?
Thanks in advance.
I wonder why people say: "Inheriting class doesn't inherit the constructor".
Perhaps it is best to illustrate this with an example:
struct Foo
{
Foo(int, int) {}
};
struct Bar : Foo
{
};
What it means is that there is no Bar::Bar(int, int) constructor that you can call, despite the existence of a constructor with the same parameter list in the base class. So you cannot do this:
Bar b(42, 42);
In C++11, you can actually inherit constructors, but you must be explicit about it:
struct Bar : Foo
{
using Foo::Foo;
};
Now, you can say Bar b(42, 42);
What they mean is that constructor signatures are not inherited.
In your example, B does not have a constructor taking a single const int& even though its base class does. In this sense it has not "inherited" the constructor (but can still make use of it).
I think what they mean is:
struct A {
A(int, int) { }
};
struct B : public A {
};
int main()
{
A a(1, 2); // ok
B b(1, 2); // error
}
To compare with “non-special” member functions:
struct A {
void f() { }
};
struct B : public A {
};
int main()
{
A a;
B b;
a.f(); // ok
b.f(); // ok too
}
But of course, from within B you can call accessible A constructors (as automatically generated ones do). Ditto for the destructor.
Note that in C++11 you can use the “inheriting constructors” feature:
struct A {
A(int, int) { }
};
struct B : public A {
using A::A;
};
int main()
{
A a(1, 2); // ok
B b(1, 2); // ok now
}
A derived class can/must see base class constructors in order to invoke them, for consistency. However, their signature is not exposed in the derived class, hence, one cannot construct the class without an explicitly defined constructor, which forwards the required arguments to the base class constructor.
In C++11, one can inherit constructors: What is constructor inheritance?
Another approach to circumvent 'proxy constructors' in C++ < 11: How to define different types for the same class in C++
In your example, the default ("parameterless" as you say) constructor of B does invoke the default constructor of A, but this does not mean that B "inherited" that constructor, only that it "has access to" it. That is, A's default constructor is accessible from within B, yet it is not accessible from outside (no one can use A's default constructor from outside to construct an instance of B).
Another way to look at it is to ask, what is something frustrating about constructors and inheritance in C++? A common answer from some people (including myself) would be that there is no automatic facility which allows "pass-through" construction of base classes taking arguments from derived class constructors without explicitly declaring and defining the latter.
I run into MISRA C++ 2008 Guidelines, and a rule 12-8-2 in this guideline says:
The copy assignment operator shall be declared protected or private in an abstract class.
and then I thought, when I make an abstract class's assignment operator public,
Is it possible to call it from another class except its subclass?
I think it's impossible.
If this is true, why they define this rule?
Basically, from the point of view of class design, I don't use abstract class which has private member, and I don't define assignment operator in a base class. So, usually, there is no need to apply this rule. However, If there is an abstract base class's public assignment operator, I would make it protected (or private if possible), because it makes no sense to be public. Do you know any other good reasons to apply this rule?
Did I overlook anything?
If they consider a class with virtual function (not pure) an abstract, then most likely to prevent slicing. Normal terminology for it is base class.
#include <iostream>
struct A
{
virtual ~A(){}
virtual void foo(){ std::cout<<1<<std::endl; };
};
struct B : A
{
virtual void foo(){ std::cout<<2<<std::endl; };
};
int main()
{
B b;
A a = b; // ops, wrong output because of slicing
}
However, if your class is really abstract (meaning it has pure virtual methods), then the rule makes no sense.
struct A
{
virtual ~A(){}
virtual void foo() = 0;
};
struct B : A
{
virtual void foo(){}
};
int main()
{
B b;
A a = b; // compilation error
}
I don't define assignment operator in a base class.
It doesn't matter whether you define the assignment operator or not. If you do not do it, the compiler will generate one for you.
Abstract class are the classes whose implementation is unknown but you know how they will behave or interact with other classes. Hence it is unlikely that you know size or other details about abstract class which is actually needed in copy and assignment operators.
Also main problem comes with something earlier answers to this post talks about "Slicing problem" which becomes more problematic in polymorphic classes as assignment operator is not by default virtual.
Consider this
class A
{
};
class B : public A
{
}
int main()
{
B b1;
B b2;
A& a_ref = b2;
a_ref = b1;
}
Now in above case a_ref is initialised to b2 object but in next line when it is assigned to b1 it will be A's operator= is called rather than B's operator= which might change other object b2. You can imagine situation where in class A and B are not empty.
Hence it is rule that you either make copy constructor and assignment operator as private not public and in case you make assignment operator public in Abstract class then make it virtual and in every derived implementation check compatibility using dynamic_cast.
By definition, abstract classes cannot be instantiated (e.g. see here). A class that cannot be instantiated cannot be copied. Therefore the rule is absurd.
I confirmed slicing problem pointed out by #BЈовић and #NIRAJ RATHI,
then I noticed a case that It's possible to call public assignment operator in abstract base class by using reference. It's possible but possibly causing slicing problem. So making assignment operator virtual, overriding it in subclass and downcasting is needed.
#include <stdio.h>
class X {
public:
int x;
X(int inx): x(inx) {}
virtual void doSomething() = 0;
virtual void print() { printf("X(%d)\n",x); }
virtual X& operator=(const X& rhs) {
printf("X& X::operator=() \n");
x = rhs.x;
return *this;
}
};
class Y : public X {
public:
int y;
Y(int inx,int iny) : X(inx), y(iny) {}
void doSomething() { printf("Hi, I'm Y."); }
virtual void print() { printf("Y(%d,%d)\n",x,y); }
virtual X& operator=(const X& rhs);
};
X& Y::operator=(const X& rhs) {
printf("X& Y::operator=() \n");
const Y& obj = dynamic_cast<const Y&>(rhs);
X::operator=(rhs);
y = obj.y;
return *this;
}
int main()
{
Y a(1,2);
Y a2(3,4);
X& r = a;
r = a2; // calling assignment operator on ABC without slicing!!
r.print();
}
In my conclusion:
- It's possible to call assignment operator in abstract base class by using reference.
- The rule 12-8-2 is intended to prevent slicing problem.
- If there is no slicing problem, I don't always have to apply the rule 12-8-2.
BЈовић: However, if your class is really abstract (meaning it has pure virtual methods), then the rule makes no sense.
It does, as the assignment operator could accidentaly be called on pointers/references to the base class, which would always lead to slicing.
class cA
{
public:
int x;
virtual ~cA() { }
virtual void f() = 0;
};
class cB: public cA
{
int y;
virtual void f() { }
};
cA * a = new cB, * b = new cB;
*a = *b; // slicing: x is copied, y is not
The rule does make sense for a couple of reasons:
prevent partial assignment
prevent copying between incompatible classes
Suppose we have an abstract base class Animal and a couple of derived classes, Lizard and Chicken:
class Animal {
public:
...
};
class Lizard: public Animal {
...
};
class Chicken: public Animal {
...
};
The assignment operator by default is public. Now consider this code:
Lizard liz1;
Lizard liz2;
Animal *pAnimal1 = &liz1;
Animal *pAnimal2 = &liz2;
...
*pAnimal1 = *pAnimal2;
The assignment operator invoked on the last line is that of the Animal class, even though the objects involved are of type Lizard. Therefore, only the Animal part of liz1 will be modified. This is a partial assignment. After the assignment, liz1's Animal members have the values they got from liz2, but liz1's Lizard members remain unchanged.
It also possible via Animal pointers to assign a Lizard to a Chicken. That doesn't make a lot of sense, since they are incompatible with each other, and we might want to prevent such a thing happening. The easiest way to prevent such assignments is to make operator= protected in Animal. That way, lizards can be assigned to lizards and chickens can be assigned to chickens, but partial and mixed-type assignments are forbidden:
class Animal {
protected:
Animal& operator=(const Animal& rhs);
...
};
Alternatively, the assignment operator can be defined =delete if copying is to be prohibited in this class hierarchy. Actually, assignment operators that are private or protected needn't return *this at all. They can return the type void.
I want to know the below code is correct or not
class A
{
public :
int show (int x, int y);
};
class B : public A
{
public :
float show (int a, int b); // can i overload this function ?
};
the show function is present in both base and derived class with different written types.
I know function overloading concept (can not overload with different return types).
Is this possible to do so?
The code will be compiled successfully. The method A::show will not be overloaded but hidden.
You can call this method with the scope operator.
Check this link or this link
Class A
{
Public :
virtual int show (int x, inty) = 0;
};
class B:Public A
{
Public :
float show (int x, int y);
};
When i declare base obj and point it to derived class :
A aObj;
B bObj;
aObju = &bObj;
bObj.Show(); // Which function will be called base class or derived class?
If you create a derived class object like
1)
B b;
b.show();
OR
2)
A* b = new B();
b->show();
Will always look into derived class, and call B::show().
This is for your particular example, where no virtual functions are present, if virtual functions are present in the base class, the second case can give different results in other cases, but in this particular example even base class virtual functions will make no difference.