When protected protects too much - c++

This is about "protected", which is explained as: "When a class inherits another one, the members of the derived class can access the protected members inherited from the base class." However, look at this code:
class Base {
public:
Base( int m ) : member(m){}
protected:
int member;
};
class Derived : public Base { // one of several subclasses
public:
Derived( int m ) : Base(m), value(10) {}
int diff( Base x ){
return value - x.member;
}
private:
int value;
};
Derived accesses "x.member", which is protected in its Base class, right? But the compiler flags an error, "Base::member is protected". And, after mulling this over for a minute, I had to agree with the compiler.
And here comes the question: How do I make this work, with a minimum loss of information hiding?
Clearly, making "member" public compiles, but it's against the original intent.
Using the "friend" mechanism in Base to let subclasses access "member" (and everything else that's private and protected) is even worse (apart from the dumb binding of a superclass to its own subclasses - a maintenance nightmare).
In the simple example, a public int getMember(){ return member; } would be acceptable. But if member's type is a X*, the best you can do is a public const X* getMember(){...}.
Did I miss something?

You can keep the protected attributes, add the getter functions as you mentioned. As for a protected pointer attribute, the getter would make sure that int (or a const ref for a large object) is returned and you can do the difference in a function template that takes Derived and Base arguments then (getters give you the values for the calculation).
Protecting data attributes allows direct access to the protected attribute within the derived class. What you tried is to access a private attribute of another object. This part of your code:
int diff( Base x ){
return value - x.member;
}
would be equivalent to writing this in main:
Base x;
cout << x.member << endl;
Here is an example of how to solve the problem using the option 3 you suggested yourself, with a derived class PointerDerived that is using pointers for the storage:
#include <iostream>
class Base {
public:
Base( int m ) : member(m){}
int getMember() const
{
return member;
}
protected:
int member;
};
class Derived : public Base { // one of several subclasses
public:
Derived( int m ) : Base(m), value(10) {}
int getValue() const
{
std::cout << "protected = " << member << std::endl;
return value;
}
private:
int value;
};
class PointerDerived : public Base { // one of several subclasses
public:
PointerDerived( int m ) : Base(m), value(new int (10)) {}
int getValue() const
{
std::cout << "protected = " << member << std::endl;
return *value;
}
~PointerDerived()
{
delete value;
value = nullptr;
}
private:
int* value;
};
template<typename Derived, typename Base>
int diff(const Derived& d, const Base& b)
{
return d.getValue() - b.getMember();
}
using namespace std;
int main(int argc, const char *argv[])
{
PointerDerived p(23);
Base q(1);
cout << diff(p, q) << endl;
return 0;
}
Compile the program with -std=c++11 because of the nullptr, or change it to NULL.
You make the diff a function template, so that you don't have to overload it for each and every derived class, and you let the derived class handle the storage and access to it as does for example PointerDerived.

You can use a static protected accessor:
class Base {
public:
Base( int m ) : member(m){}
private:
int member;
protected:
static int GetMember(const Base &b)
{ return b.member; }
};
class Derived : public Base { // one of several subclasses
public:
Derived( int m ) : Base(m), value(10) {}
int diff( Base &x ){ //beware of your slicing!
return value - GetMember(x);
}
private:
int value;
};
Now let me add my idea of why C++ access control works this way...
Access control in C++ is not about information hiding. It is about encapsulation. That is, plainly speaking, you filter out the access to any member that can break the class if used incorrectly.
In an ideal class
public members cannot be used to break the object.
private members know what they are doing.
As you see, in my scheme there is little place for protected members:
protected members are used to implement the inheritance interface, if any.
And even less place for protected member variables.
So make your variable private, and write a protected accessor. The accessor must be static to be able to be used from the derived object.

Related

Const and non-const version and inheritance

In my problem, I will have a few classes that will share getters and setters (in my case, the operator()). Suppose I have the following
class Base
{
public:
int& operator()() { return value; }
int operator()() const { return value; }
protected:
int value;
};
class Derived : public Base
{
public:
int operator()() const { return value; }
};
I expected being able to do something like this :
Derived d;
d() = 1;
but the compiler complains saying that the expression is not assignable. However, doing this
Derived d;
d.Base::operator()() = 1;
works correctly. Why is that ? Shouldn't the compiler be able to look up for the member function in the base class ? Is there a solution to avoid rewriting the non-const method is the derived class ?
Shouldn't the compiler be able to look up for the member function in the base class?
Yes, it is possible, but you have to be explicit. For that you can use a using declaration, which introduces the operator to the derived class:
class Derived : public Base
{
public:
using Base::operator();
int operator()() const { return value; }
};

Giving derived class only const access to base class data members/functions

In my specific case, I have a base class 'Base', with a data member 'A_var'. I'd like that any derived classes only have const access to that data member, in a syntactically equal fashion to the 'Base' class.
If it's protected or private, then derived classes have full or no access, respectively. I could make it private, and make a protected function that returns a const reference, but then the access would be syntactically different.
class Base {
protected:
const type_t& A() const {return A_var;}
private:
type_t A_var;
void f();
};
class Derived : public Base{
public:
void g();
};
//access in Base class
void Base::f() {
type_t value = A_var;
A_var = value;
}
//access in Derived class
void Derived::g() {
type_t value = A();
A() = value; //Error, const reference; good
}
Overloading 'A()', as below, also doesn't work, because the 'Derived' class calls the private non-const 'A()'.
protected:
const type_t& A() const {return A_var;}
private:
type_t& A() {return A_var;}
The small difference may not seem like a big deal, but in my code there are various macros that start with access to that data member. As such, I have to have different macros for the 'Base' class and derived classes, which disrupts the flow of the code, both reading and writing.
Update:
To clarify, the issue is one of making the access in the derived and base classes the same, syntactically. That is, for instance, that I could call a function f(), and have it return a non-const reference when called in the base class, but a const reference when called in a derived class. The motivation is to make the forced const access in derived classes seamless. I realize there may not be a way to do this, but I asked just in case.
Update:
To present a real example (there are 2-3 of such cases), this is used a lot in the code:
test_files_var.current()->current_test()
I replaced that with a
#define TEST() test_files_var.current()->current_test()
because the derived class would access test_files_var through a different function/member, i.e. testFiles(), I have to have a second definition of TEST(), i.e. DTEST(). The problem is given more by the number of times the 'macros' are used, than by how many of them there are.
Where is no simple built-in solution.
But a bit of template magic can probably do a trick:
template <class NonConst>
struct Matcher {
template <class AnyOther>
static const AnyOther &get(AnyOther &obj) { return obj; }
static NonConst &get(NonConst &obj) { return obj; }
};
class Base {
public:
Base() : a_(42) { }
public:
virtual void Fun() {
Matcher<Base>::get(*this).A();
}
const int &A() const {
std::cout << "const" << std::endl;
return a_;
}
int &A() {
std::cout << "no const" << std::endl;
return a_;
}
private:
int a_;
};
class Derived : public Base {
public:
void Fun() {
Matcher<Base>::get(*this).A();
}
};
int main(int argc, const char * argv[]) {
Derived d;
d.Fun();
Base b;
b.Fun();
return 0;
}
The code above will output: const no const.
So in both Fun functions you have essentially the same access pattern which you could wrap in a macros if you need.
If I understand your question correctly, you want to give access to the derived classes access to a private variable of the base class but in read only.
In this case, you just have to define a protected constant reference variable and intialize it to the private variable:
class Base {
public:
Base() : cA(A_var) { ... } // to be completed with rule of 3
protected:
const type_t& cA;
private:
type_t A_var;
void f();
};
The access in the derived class uses then the constant reference:
//access in Derived class
void Derived::g() {
type_t value = cA;
//cA = value; //Error, const reference: can't assign
}
Live demo
You may change your Base class to
class Base {
public:
Base() : A_cref(A_var) {}
private:
type_t A_var;
void f();
protected:
const type_t& A_cref;
};
with the extra member overhead.
If the macros are usable from the derived classes, they can only need const access - so the macros can use the protected const access function.
Macros that are going to modify the variable will have to use the private variable, and will only be usable in the base class.
It appears that you problems will go away if you replace your TEST() macro with the public function test() in the base class:
class Base
{
public:
void test() { test_files_var.current()->current_test() }
private:
type_t test_files_var;
};

Reaching inherited variables with base class pointers

I learnt the work of virtual functions: if the inherited classes inherit a function from the base class, and it is custom for each ones, I can call these functions with pointers that point to the base class, this way:
BaseClass* PointerName = &InheritedClassObject;
But what about variables? I found this question on the site that tells: I can't create virtual variables in C++. My experience proves it: for variables, Visual C++ says: 'virtual' is not allowed.
Then, what is the way to reach the value of a(n inherited) variable that belongs to an inherited class by using base class pointers?
Based off your comment, I think what you are trying to ask if how do child classes access their parent's variables. Consider this example:
class Parent
{
public:
Parent(): x(0) {}
virtual ~Parent() {}
protected:
int x;
};
class Child: public Parent
{
public:
Child(): Parent(), num(0) {}
private:
int num;
};
void Child::foo()
{
num = x; //Gets Parent's x,
}
NB: If you define an x in Child, that masks the x in Parent. So, if you want to get the x in Parent, you would need: Parent::x. To simply get x from a Child c, you use c.x if x is public or use a getter if x is protected or private:
int Child::getNum()
{
return num;
}
You don't. Virtual functions use them, do whatever needs to be done and return result if needed.
You can't use any function, data member of an inherited class if it's casted back to base class. However, you can alter those variables with virtual functions. Example:
#include <iostream>
class BaseClass {
public:
BaseClass() {}
virtual void do_smth() = 0;
private:
};
class InheritedClass: public BaseClass {
public:
InheritedClass(): a(1) {}
virtual void do_smth() { std::cout << ++a << std::endl; }
private:
int a;
};
int main() {
BaseClass* ptr = new InheritedClass();
ptr->do_smth();
return 0;
}
In this piece of code, virtual function did alteration of variable belongs to InheritedClass.

How to Avoid Duplicate copies of Base Class Members in Derived Class in C++

In my project, there is one Base class and there are 3 different derived classes. I have some macro variables written as const int in the base class. All the derived member is going to access these members and are going to see the same value. Since, its a const, and it is not going to change, maintaining 3 different values will be waste of space. Hence I want a way to maintain just one copy of base class const members so that all the derived class will use the same.
Example
//Base.hpp
Class Base {
const int ZER0;
const int ONE;
};
//Derived1.hpp
class Derived1:public Base {
int some_method1();
};
//Derived1.cpp
int Derived1::some_method1() {
int value = ZERO;
}
//Derived2.hpp
class Derived2:public Base {
int some_method2();
};
//Derived2.cpp
int Derived2::some_method2() {
int value = ONE;
}
//main.cpp
Derived1 d1;
d1->some_method1();
Derived d2;
d2->some_method2();
//Here in both the methods the values are constant, but still the ZERO and ONE are going to have different space. Is there a way, where I maintain only one copy? I could think of static variable. Is it okay to use static inside class and where do I initialize the static variable. Please advice.
PS: This questions might be a duplicate, but I cant find something with similar words, if you feel this is, please feel free to redirect to the corresponding article/question;
If I'm understanding you correctly, would an enum do what you're looking for?
class Base
{
enum
{
ZERO,
ONE
};
};
I think you can possibly use virtual base inheritence to maintain one copy of base ..
//Base.hpp
class Base {
public:
Base() {}
virtual ~Base() {}
protected:
static const int ZER0;
static const int ONE;
};
//Base.cpp
const int Base::ZER0 = 0;
const int Base::ONE = 1;
//Derived1.hpp
class Derived1 : public virtual Base { //using virtual keyword here maintains one copy of base class, thus one copy of ONE and ZERO for all objects since they are static members of Base. You must read about diamond problem of virtual inheritence to understand this properly.
public:
Derived1() :Base() {}
int method1();
};
//Derived1.cpp
int Derived1::method1() {
int value = ZER0;
return value;
}
//Derived2.hpp
class Derived2 : public virtual Base {
public:
Derived2() :Base() {}
int method2();
};
//Derived2.cpp
int Derived2::method2() {
int value = ONE;
return value;
}
//main.cpp
int main() {
Derived1 d1;
d1.method1(); // . instead of -> , -> is used for member access through pointers
Derived2 d2;
d2.method2();
return 0;
}

c++ redefining types in subclasses and slicing

#include <string>
#include <iostream>
class a { public: int x;};
class b : public a {public: int x; } ;
int main()
{
b bee;
bee.x = 3;
a ay = bee;
std::cout << std::endl << ay.x << std::endl;
}
The code above compiles fine in clang 3.0 and g++ 4.5. However the output is junk (--i.e., not three). Since the compiler doesn't seem to mind, how do I get the code to behave ?
Secondly, If there is some way to make the above slice / conversion to work correctly, how bad would it be if I then did the following, provided a good reason to do it exists :
class c : public a { public: uint64_t x; };
Why I am interested in these semantics.
The reason I want to do this is this. I have a two class heirachies, where one heirarchy (the parent) aggregages objects, on the same heirarchy level, from the other(the child). I use a custom container for the aggregation. I want to typedef the container in the parent class (the typedefs have the same name), and declare the container with the same name at each level of the parent.
The class heirarchies are designed to contain less information at lower levels ( the base classes hold the least), therefore slicing makes perfect sense here.
Edit:
There you go, this should clear things up.
class A { int x; };
class B : public A {int y;};
class Ap {std::vector<A> entries;};
class Bp : Ap{std::vector<B> entries;};
The child B has more members than the child class A. However, I wan't to present a uniform interface for code that is only interested in the members of class A.
There is no way to do that if you directly set b::x. a::x and b::x are two different members, and the latter hides the former.
You can still access a::x on an object of type b with static_cast<a&>(bee).x = 3, but the fundamental problem is that the values of a::x and b::x on an object of type b are not synchronized.
If you abstract access to both x members with a "property getter/setter", then you can arrange for the setter on the derived class to also update the member of the base class. Or (maybe this is more appropriate?) you can make the member of the base class protected and use it from the derived class directly, slicing as you need just before returning from the getter.
huh ! its a bit complicated no ?
why don't you use :
class a
{
virtual void set( int value ) { x = value; }
protected :
int x;
};
class b : public a
{
virtual void setA( int value ) { a::x = value; }
or
virtual void setA( int value ) { b::x = value; }
or
virtual void setA( int value ) { a::x = value; b::x = value; }
protected:
int x;
} ;
There are two ways of constructing a software design; one way is to make it so simple that there are obviously no deficiencies, and the other way is to make it so complicated that there are no obvious deficiencies. The first method is far more difficult.
C.A.R.Hoare
According to Jon's answer, Since a::x and b::x are separate variables, furthermore since b::x masks a::x, if you wanted to get the correct semantics you need to provide a copy conversion constructor. The following code does the trick.
#include <string>
#include <iostream>
class b;
class a {
public:
a();
a(const b & bee);
int x;
};
class b : public a {public: int x; } ;
a::a() {}
a::a(const b & bee)
{
x = bee.x;
}
int main()
{
b bee;
bee.x = 3;
a ay = bee;
std::cout << std::endl << ay.x << std::endl;
}
Maybe try something like this:
class A { int x; };
class B : public A {int y;};
class Ap {
public:
void Append(A *pa)
{
entries.push_back(pa);
}
A *GetA(size_t nIndex)
{
return entries.at(nIndex);
}
private:
std::vector<*A> entries;
};
class Bp : Ap
{
public:
B *GetB(size_t nIndex)
{
return dynamic_cast<B*>(GetA(nIndex));
}
};