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);
}
Related
#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.
Hi i need help with this little example.
I am unable to use _test from the nested class
class random
{
public:
int _test;
class nestedClass
{
public:
void notify() override {
_test = 123;
}
} _nestedClass;
};
You can use/pass a pointer to the outer class named random to achieve what you want as follows:
void notify(random* p)
{
p->_test = 123;
}
This is because a nested class can access a non-static member of the enclosing class through a pointer to the enclosing class.
You can also pass arguments as:
void notify(random* p, int i)
{
p->_test = i;
}
You can't access the non-static member of random without a instance of random. You need to tell your nestedClass which _test it want to access. There may be many instances of random out there, and therefor, many _tests.
I think what you want is:
class random
{
public:
int _test;
class nestedClass
{
random& outer_;
public:
nestedClass(random& outer): outer_(outer) {
}
void notify() {
outer_._test = 123;
}
} _nestedClass;
random(): _nestedClass(*this) {
}
};
#include <iostream>
class virtualClass{
public:
virtual int a() = 0;
};
class UnknownImplementation : public virtualClass{
public:
int a() override { return 1;}
};
class myFramework {
public:
int c(int (virtualClass::*implementedFunc)(void)){
implementedFunc();
return 2;
}
};
int main(){
//some user implements the virtual class and calls myFramework function
myFramework* mfp = new myFramework();
std::cout << mfp->c(&(UnknownImplementation::a)) << std::endl;
}
Hi, I am working on a framework that is supposed call an implemented virtual function and use it. It is similar to the code above.
The compiling errors I get are:
testVirtual.cpp: In member function ‘int myFramework::c(int (virtualClass::)())’: testVirtual.cpp:16:19: error: must use ‘.’ or
‘->’ to call pointer-to-member function in ‘implementedFunc (...)’,
e.g. ‘(... -> implementedFunc) (...)’ implementedFunc();
^ testVirtual.cpp: In function ‘int main()’: testVirtual.cpp:24:47: error: invalid use of non-static member
function ‘virtual int UnknownImplementation::a()’ std::cout <<
mfp->c(&(UnknownImplementation::a)) << std::endl;
How do I fix these problems?
Thanks in advance!
passing an instance of the implemented class and calling the function worked.
To build on sameerkn's comment, this code should be:
#include <iostream>
class virtualClass{
public:
virtual int a() = 0;
};
class mySubclass : public virtualClass{
public:
int a() override { return 1;}
};
int main(){
mySubclass * x= new mySubclass ();
// ...
std::cout << x->a () << std::endl;
}
The point here is that you can pass objects (or pointers) of type virtualClass around - even though they might actually be mySubclass objects in real life - and still wind up in the right implementation of a(). myFramework is entirely unnecessary.
That's what virtual methods are for - consumers of virtualClass don't need to know anything about classes that might - now or in the future - be derived from it, and if I have read your question correctly, this is what you want.
Here is what I'm trying to accomplish:
-Client registers a function (fun) with the class (foo)
-Fun has a general form type function(int, int,int)
-Foo then, in executing its work, calls that function which may require access to private members.
The point is to allow user defined functions which Foo can use in the course of its work. Is there a pattern/nuance of C++ etc.. that would make this feasible?
Worst case scenario I can make the data public but I'm curious if something better exists.
TIA
Example:
class foo;
typedef float (*client_fun)(foo &obj, int &i);
class foo
{
client_fun their_fun;
int private_info;
public:
foo(): private_info(42){};
void set_fun(client_fun _fun)
{
their_fun = _fun;
}
float run_foo()
{
//Oversimplified example of what it would be doing.
//their_fun would be called as part of a complicated method
int i;
i = 1;
return their_fun(*this, i);
}
};
float fancy_fun(foo &obj, int &i)
{
//needs access to private info
return (i/obj.private_info);
}
int main()
{
//Hypothetical use
foo my_foo;
my_foo.set_fun(fancy_fun);
//Can't access the private member
my_foo.run_foo();
return 0;
}
G++ example.cpp:
example.cpp: In function ‘float fancy_fun(foo&, int&)’:
example.cpp:8:8: error: ‘int foo::private_info’ is private
int private_info;
^
example.cpp:32:18: error: within this context
return (i/obj.private_info);
This is the pattern that answers my question.
#include <iostream>
class engine;
class settings
{
//Can friend the engine class if we have private members we want to be able to call
friend class engine;
public:
int private_info;
settings()
{
private_info = 42;
};
};
typedef float (*fn_ptr)(settings &);
class engine
{
//private info will still be private to the world since the engine owns the settings object
settings my_settings;
fn_ptr my_fn;
public:
engine(): my_settings(){};
void set_fun(fn_ptr _ptr)
{
my_fn = _ptr;
}
void run()
{
std::cout << my_fn(my_settings, 1) << "\n";
}
};
float fancy_fun(settings &obj, size_t i)
{
//needs access to private info
return (obj.private_info);
}
int main()
{
//Hypothetical use
engine my_engine;
my_engine.set_fun(fancy_fun);
//Error! Private!
//my_engine.my_settings;
/*Is now accessing the public member of a private object
* using an appropriately specified user function */
my_engine.run();
return 0;
}
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;
}