#include <iostream>
#include <string>
int ival = 3;
class Base {
public:
Base(int val) : ival(val){}
int ival;
};
class Derived : public Base {
public:
Derived(int val) : Base(val+1), ival(val) {}
void show(){
std::cout << "ival = " << ival << "\n"; // 1
std::cout << "Base::ival = " << Base::ival << "\n"; // 2
std::cout << "::ival = " << ::ival << "\n"; // 3
}
int ival;
};
int main() {
Derived d(1);
d.show();
return 0;
}
d is an object of the Derived class. The scope of the Base class is searched for ival first. It is not
found.Derived is derived from Base, the Base class scope is next examined to find a declaration of ival. It is found to be a member of the Base base class. The reference is resolved successfully.
```c++
#include int ival = 3;
class Base { public: Base(int val) : ival(val){} int ival; };
class Derived : public Base { public: Derived(int val) : Base(val+1){}
void show(){
std::cout << "ival = " << ival << "\n"; // 2
} };
int main() {
Derived d(1);
d.show();
return 0; } ```
#include <iostream>
#include <string>
int ival = 3;
class Base {
public:
};
class Derived : public Base {
public:
Derived(int val) : Base(){}
void show(){
// Error: ival is not a member of Base
std::cout << "ival = " << Base::ival << "\n";
}
};
int main() {
Derived d(1);
d.show();
return 0;
}
int dval; // global variable
class ZooAnimal {
private:
int dval; // private member
};
int Bear::mumble(int ival) {
foo(dval);
}
The dval in foo(dval) resolves to the private ZooAnimal::dval, even though it’s inaccessible — so the code will give a compile-time error.
But imagine the class designer later changes this to:
class ZooAnimal {
protected: // just changed access
int dval;
};
Now suddenly, ZooAnimal::dval is accessible, so foo(dval) now calls a different overload of foo(), because the argument is now an int from the class instead of the global int dval.
#include <iostream>
class ZooAnimal {
public:
void gender(){
std::cout << "ZooAnimal::gender()\n";
}
void color(){
std::cout << "ZooAnimal::color()\n";
};
void highlight() {
std::cout << "ZoomAnimal::highlight()\n";
};
};
class Endangered {
public:
void highlight() {
std::cout << "Endangered::highlight()\n";
};
void print() {
std::cout << "Endangered::print()\n";
}
};
class Bear : public ZooAnimal {
public:
void color(){
std::cout << "Bear::color()\n";
}
};
class Panda : public Bear, public Endangered {
public:
};
int main() {
Panda p;
p.color(); // Bear::color()
p.gender(); // ZooAnimal::gender()
p.print(); // Endangered::print()
//p.highlight(); // Error: ambiguous
p.ZooAnimal::highlight(); // ZoomAnimal::highlight()
p.Endangered::highlight(); // Endangered::highlight()
}
highlight() functions from the ZooAnimal and Endangered base classes, no error message is issued until an ambiguous attempt to reference either of those functions occurs.Endangered and the Bear/ZooAnimal subtrees. If a declaration is found in only one base class subtree, the identifier is resolved and the lookup algorithm concludes. This is what happens with the invocation of gender().highlight(). p.ZooAnimal::highlight(); // ZoomAnimal::highlight()
p.Endangered::highlight(); // Endangered::highlight()
While this solves the problem, in general it is not a satisfactory solution. The reason is that the user has now been placed in the position of having to decide what the right behavior is for the Panda class. This burden of responsibility should never be placed on the user of a class.
inline void Panda::highlight() {
Endangered::highlight();
}
inline ostream&
Panda::print( ostream &os ) const
{
Bear::print( os );
Endangered::print( os );
return os;
}