any reason not to use 'protected' in this situation (cpp, c++, oop) - c++

#include <iostream>
using namespace std;
class R {
protected:
int a;
public:
int read(void) {
return a;
}
};
class RW : public R {
public:
void write(int _a) {
a = _a;
}
};
int main(void) {
int a;
R *r = (R *)&a;
RW *rw = (RW *)&a;
rw->write(1);
cout << dec << r->read() << endl;
cout << dec << rw->read() << endl;
return 0;
}
I want to make a class that can only read (class R) and a class can read and write (class RW). Is there any reason I should not do this in oop? and also any reason not to use the 'protected' here?
Please help me, thanks for any replies!
P.S. I don't want to define duplicated 'private int a;' on both classes, because the offset of 'int a in class RW' and size of 'class RW' is not the same to the 'class R' anymore.

any reason not to use the 'protected' here?
protected member variables are sometimes discouraged in favor of protected member functions that accesses private member variables - and you don't need duplicate as if you make it private in R. You could add a protected member function to write to it instead.
class R {
public:
int read() const { // not `void` and add `const`
return a;
}
protected:
void write(int A) {
a = A;
}
private:
int a;
};
class RW : public R {
public:
void write(int A) {
R::write(A);
}
};
Without any added validation in R::write, the above basically does the same as your code, but a is private.
Your original version is not wrong though. As can be seen here: Should you ever use protected member variables? there's no definite "no, you should never use protected member variables".
One may argue that if they are only protected, one can just inherit the class and treat them as public and if changing such member variables doesn't require any validation of any sort, they could be made public to start with. One would have to look at it from case to case.

Related

How should a member class access to the member functions?

This is a question to find out the better programming practice:
In C++, say I have two classes one of which is a member class of the other, e.g.,
class SomeClass {
public:
MemberClass member_class;
void set_num(double num_) { num_ = num; }
double num() {return num_; }
private:
double num_;
}
I want the member class to have access to the member functions of the outer class, e.g.,
class MemberClass {
public:
PrintSquare() {
cout << num() * num() << endl;
}
}
I am trying to achieve this in order to reduce the number of function arguments I am passing all around the program.
The most common (and IMHO proper) way to solve this problem is, introducing an interface (or even more interfaces focusing on particular sets of method features) for the containing class, and pass that one to the 'inner' class member on construction:
struct Interface {
virtual void set_num(double num_) = 0;
virtual double num() const = 0;
virtual ~Interface() {}
};
class MemberClass {
public:
MemberClass(Interface& interface) : interface_(interface) {}
PrintSquare() {
cout << interface_.num() * interface_.num() << endl;
}
private:
Interface& interface_;
};
class SomeClass : public Interface {
public:
MemberClass member_class;
SomeClass() : member_class(*this), num_() {}
virtual void set_num(double num_) { num_ = num; }
virtual double num() const { return num_; }
virtual SomeClass() {}
private:
double num_;
};
NOTE:
Calling methods of the interface though will fail (with a runtime exception), when called from the MemberClass constructor definition.
Although the answer by Kerrek is very interesting, he himself already states this normally isn't the way to go. Common practice would be to make the inner class nested in the outer one, if possible. If the inner one needs access to the outer one in such a way that a nested connection seems natural, this would be the way to go. Construction of an Inner object would then need a reference to the object it is a member from, in order to be able to call functions on its parent:
class Outer
{
class Inner
{
Outer &parent; // consider constness
public:
Inner(Outer &_parent); //initializes the parent-reference
void innerFunction(); // can call members of parent
};
Inner inner;
public:
Outer(): inner(*this) { ... } // initialize inner
};
Depending on the standard you're using, the innerFunction now has access to all public members of Outer (C++03), or even all private members as well (C++11). See also this topic:
C++ nested classes - inner/outer relationship
EDIT: Did a quick test, and my compiler (gcc 4.7.2) also allows access to private members with older standards. Maybe someone could comment on this...
If your classes are all standard-layout, then you can take advantage of some layout guarantees that C++ makes, namely that a on object of standard layout type may be treated as if it were its own first member. For instance:
struct Foo
{
int a;
void barely_legal();
};
struct Bar
{
Foo x;
int y;
};
#include <type_traits>
void Foo::barely_legal()
{
static_assert(std::is_standard_layout<Foo>::value, "Foo");
static_assert(std::is_standard_layout<Bar>::value, "Bar");
Bar * p = reinterpret_cast<Bar *>(this);
++p->y;
}
This is unusual at best and cruel at worst, so please don't write code like this unless you have a really good reason to do so. (I know people who do have reason to do this, but I don't turn my back towards them.)

In C++ how can we call private function through an object without using friend function?

I came across this code written in C++ :
#include<iostream>
using namespace std;
class Base {
public:
virtual int fun(int i) { cout << "Base::fun(int i) called"; }
};
class Derived: public Base {
private:
int fun(int x) { cout << "Derived::fun(int x) called"; }
};
int main()
{
Base *ptr = new Derived;
ptr->fun(10);
return 0;
}
Output:
Derived::fun(int x) called
While in the following case :
#include<iostream>
using namespace std;
class Base {
public:
virtual int fun(int i) { }
};
class Derived: public Base {
private:
int fun(int x) { }
};
int main()
{
Derived d;
d.fun(1);
return 0;
}
Output :
Compiler Error.
Can anyone explain why is this happening ? In the first case , a private function is being called through an object.
Because in the first case you're using declaration from Base, which is public, and the call is being late-bound to the Derived implementation. Note that changing the access specifier in inheritance is dangerous and can nearly always be avoided.
Polymorphism is happening in the first case. It causes dynamic or late binding. And as mentioned in the second answer, it can become quite dangerous at times.
You cannot access the private interface of a class from the outside of class definition directly. If you want to access the private function in the second instance without using a friend function, as title of your question implies, make another public function in your class. Use that function to call this private function. Like this.
int call_fun (int i) ;
Call the fun() from inside it.
int call_fun (int i)
{
return fun (i) ; //something of this sort, not too good
}
The functions like this which are used just to call another function are known as wrapper functions.
Making friends is also not advisable always. It is against the principle of information hiding.

Passing objects into functions within another class c++

I'm learning about classes and objects in c++ and tried the following code to test if I understood it properly:
#include <iostream>
using namespace std;
class class1
{
public:
void write(int x)
{
dataObject.var = x;
}
};
class class2
{
public:
void read()
{
std::cout << dataObject.var;
}
};
class data
{
public:
int var;
data()
{
var = 1;
}
};
int main()
{
data dataObject;
class1 object1;
class2 object2;
object2.read(data dataObject);
object1.write(2);
object2.read(data dataObject);
return 0;
}
This was for two objects to both be used to modify and use the members of a third but I get the following errors:
In member function 'void class1::write(int)':
line 10: error: 'dataObject' was not declared in this scope
In member function 'void class2::read()':
line 14: error: 'dataObject' was not declared in this scope
In function 'int main()':
line 40 + 42: error: expected primary-expression before 'dataObject'
Any idea where I am going wrong?
Thanks in advance.
EDIT:
Thanks for all the suggestions. My code now is:
#include <iostream>
using namespace std;
class class1
{
public:
void write(data &dataObject, int x)
{
dataObject.var = x;
}
};
class class2
{
public:
void read(data dataObject)
{
std::cout << dataObject.var << endl;
}
};
class data
{
public:
int var;
data()
{
var = 1;
}
};
int main()
{
data dataObject;
class1 object1;
class2 object2;
object2.read(dataObject);
object1.write(dataObject,2);
object2.read(dataObject);
return 0;
}
And I now get the errors:
8 error: 'data' has not been declared
10 error: request for member 'var' in 'dataObject', which is of non-class type 'int'
18 error: 'data' has not been declared
20 error: request for member 'var' in 'dataObject', which is of non-class type 'int'
40 error: 'dataObject' was not declared in this scope
Where you go wrong is that at this point:
void write(int x)
{
dataObject.var = x;
}
there is no dataObject. You are trying to make your classes depend on some global object. First of all you have to decide if you really want this. And if you do, you need a way to ensure that these global objects are declared and instantiated before they get used by the classes.
There are many ways to fix the error, but first you need to be clear about what you want the classes to do and how they should interact with each other.
One example of how you could fix this without global objects:
class class1
{
public:
class1(data& dataObj) : dataRef_(dataObj) {}
void write(int x)
{
dataRef_.var = x;
}
private:
data& dataRef_;
};
Then in the main:
int main()
{
data dataObject;
class1 object1(dataObject);
object1.write(2);
}
Your classes are not aware of the variable dataObject. If you want them to be able to access instances of class data you will need to pass them to your functions. Redefine the functions like this
void read(const data& dataObject)
{
std::cout << dataObject.var;
}
or have a member variable of class data in your classes if you want to be able to do this.
From a design point of view, your classes don't do anything other than act on an instance of class data. You could combine both classes into new class that contains an object of class data as a member variable. You could have multiple functions (read/write) of that new class to do your modifications/output for the internal data member. It doesn't really make sense to have 2 separate classes whose only purpose is modifying another variable that is not a member variable.
You're passing parameters to member functions read and write, but those functions aren't defined as accepting parameters.
Redefine them as:
// for class1:
void write(data &dataObject, int x)
{
dataObject.var = x;
}
// for class2:
void read(data dataObject)
{
std::cout << dataObject.var << endl;
}
Furthermore, when you pass those objects, don't prefix them with the type data: you've already declared the variables, now you need only:
int main()
{
data dataObject;
class1 object1;
class2 object2;
object2.read(dataObject);
object1.write(dataObject, 2);
object2.read(dataObject);
}

How to access private data members outside the class without making "friend"s? [duplicate]

This question already has answers here:
Can I access private members from outside the class without using friends?
(27 answers)
Closed 6 years ago.
I have a class A as mentioned below:-
class A{
int iData;
};
I neither want to create member function nor inherit the above class A nor change the specifier of iData.
My doubts:-
How to access iData of an object say obj1 which is an instance of class A?
How to change or manipulate the iData of an object obj1?
Note: Don't use friend.
Here's a way, not recommended though
class Weak {
private:
string name;
public:
void setName(const string& name) {
this->name = name;
}
string getName()const {
return this->name;
}
};
struct Hacker {
string name;
};
int main(int argc, char** argv) {
Weak w;
w.setName("Jon");
cout << w.getName() << endl;
Hacker *hackit = reinterpret_cast<Hacker *>(&w);
hackit->name = "Jack";
cout << w.getName() << endl;
}
Bad idea, don't do it ever - but here it is how it can be done:
int main()
{
A aObj;
int* ptr;
ptr = (int*)&aObj;
// MODIFY!
*ptr = 100;
}
You can't. That member is private, it's not visible outside the class. That's the whole point of the public/protected/private modifiers.
(You could probably use dirty pointer tricks though, but my guess is that you'd enter undefined behavior territory pretty fast.)
EDIT:
Just saw you edited the question to say that you don't want to use friend.
Then the answer is:
NO you can't, atleast not in a portable way approved by the C++ standard.
The later part of the Answer, was previous to the Q edit & I leave it here for benefit of >those who would want to understand a few concepts & not just looking an Answer to the >Question.
If you have members under a Private access specifier then those members are only accessible from within the class. No outside Access is allowed.
An Source Code Example:
class MyClass
{
private:
int c;
public:
void doSomething()
{
c = 10; //Allowed
}
};
int main()
{
MyClass obj;
obj.c = 30; //Not Allowed, gives compiler error
obj.doSomething(); //Allowed
}
A Workaround: friend to rescue
To access the private member, you can declare a function/class as friend of that particular class, and then the member will be accessible inside that function or class object without access specifier check.
Modified Code Sample:
class MyClass
{
private:
int c;
public:
void doSomething()
{
c = 10; //Allowed
}
friend void MytrustedFriend();
};
void MytrustedFriend()
{
MyClass obj;
obj.c = 10; //Allowed
}
int main()
{
MyClass obj;
obj.c = 30; //Not Allowed, gives compiler error
obj.doSomething(); //Allowed
//Call the friend function
MytrustedFriend();
return 0;
}
http://bloglitb.blogspot.com/2010/07/access-to-private-members-thats-easy.html
this guy's blog shows you how to do it using templates. With some modifications, you can adapt this method to access a private data member, although I found it tricky despite having 10+ years experience.
I wanted to point out like everyone else, that there is an extremely few number of cases where doing this is legitimate. However, I want to point out one: I was writing unit tests for a software suite. A federal regulatory agency requires every single line of code to be exercised and tested, without modifying the original code. Due to (IMHO) poor design, a static constant was in the 'private' section, but I needed to use it in the unit test. So the method seemed to me like the best way to do it.
I'm sure the way could be simplified, and I'm sure there are other ways. I'm not posting this for the OP, since it's been 5 months, but hopefully this will be useful to some future googler.
In C++, almost everything is possible! If you have no way to get private data, then you have to hack. Do it only for testing!
class A {
int iData;
};
int main ()
{
A a;
struct ATwin { int pubData; }; // define a twin class with public members
reinterpret_cast<ATwin*>( &a )->pubData = 42; // set or get value
return 0;
}
There's no legitimate way you can do it.
Start making friends of class A. e.g.
void foo ();
class A{
int iData;
friend void foo ();
};
Edit:
If you can't change class A body then A::iData is not accessible with the given conditions in your question.
iData is a private member of the class. Now, the word private have a very definite meaning, in C++ as well as in real life. It means you can't touch it. It's not a recommendation, it's the law. If you don't change the class declaration, you are not allowed to manipulate that member in any way, shape or form.
It's possible to access the private data of class directly in main and other's function...
here is a small code...
class GIFT
{
int i,j,k;
public:
void Fun()
{
cout<< i<<" "<< j<<" "<< k;
}
};
int main()
{
GIFT *obj=new GIFT(); // the value of i,j,k is 0
int *ptr=(int *)obj;
*ptr=10;
cout<<*ptr; // you also print value of I
ptr++;
*ptr=15;
cout<<*ptr; // you also print value of J
ptr++;
*ptr=20;
cout<<*ptr; // you also print value of K
obj->Fun();
}
friend is your friend.
class A{
friend void foo(A arg);
int iData;
};
void foo(A arg){
// can access a.iData here
}
If you're doing this regularly you should probably reconsider your design though.
access private members outside class ....only for study purpose ....
This program accepts all the below conditions
"I dont want to create member function for above class A. And also i dont want to inherit the above class A. I dont want to change the specifier of iData."
//here member function is used only to input and output the private values ...
//void hack() is defined outside the class...
//GEEK MODE....;)
#include<iostream.h>
#include<conio.h>
class A
{
private :int iData,x;
public: void get() //enter the values
{cout<<"Enter iData : ";
cin>>iData;cout<<"Enter x : ";cin>>x;}
void put() //displaying values
{cout<<endl<<"sum = "<<iData+x;}
};
void hack(); //hacking function
void main()
{A obj;clrscr();
obj.get();obj.put();hack();obj.put();getch();
}
void hack() //hack begins
{int hck,*ptr=&hck;
cout<<endl<<"Enter value of private data (iData or x) : ";
cin>>hck; //enter the value assigned for iData or x
for(int i=0;i<5;i++)
{ptr++;
if(*ptr==hck)
{cout<<"Private data hacked...!!!\nChange the value : ";
cin>>*ptr;cout<<hck<<" Is chaged to : "<<*ptr;
return;}
}cout<<"Sorry value not found.....";
}

calling member function without object error: C++ / (G++) oop

i was curious to know why the following throws an error in g++ (cannot call member function without object). I suppose a workaround would be to have the B class variable as static variable in A - but i was curious to find out why, when there is an instance of A's child class C created, this still throws an error - many thanks!
#include <iostream>
#include <cstring>
using namespace std;
class B {
public:
double var;
public:
friend class A;
B() : var(1) { };
void set(double new_rate);
};
class A {
protected:
B main_B;
public:
virtual void set_rate(double new_rate) { cout << "test";
//B.set(new_rate);
}
};
class C : public A {
};
/*
void B::set(double new_rate) {
var = new_rate;
cout << "worked " <<current_rate <<endl;
}
*/
int main() {
C test_C;
A::set_rate ( 2.00 );
return 0;
}
Firstly,
C test_c();
does not create an instance of C, it declares a function that returns a C. You mean:
C test_c;
Secondly, non-static member functions can only be called on a specific instance of a class. So with the corrected code, you could say:
test_c.set_rate( 2.0);
You can use an explicit <class>:: to call a non-static member function, thereby disabling any virtual function mechanism, but for a non-static member you still need to specify a class instance on which to call the function.
e.g.
int main()
{
C test_C;
test_C.A::set_rate(2.00);
return 0;
}