trying to modify object in the class via get/set methods. I can't understand how change value just only use get/set method.
expected output : "Output : 89".
actual output : "Output : 0"
#include<iostream>
using namespace std;
class TestClass{
public:
int getValue() const{
return _value;
}
void setValue(int value) {
_value = value;
}
private:
int _value;
};
class A{
public:
TestClass getTestClass() const{
return _testClass;
}
void setTestClass(TestClass testClass) {
_testClass = testClass;
}
private:
TestClass _testClass;
};
int main()
{
A a;
a.getTestClass().setValue(89);
cout<<"Output :"<<a.getTestClass().getValue();
}
replace
TestClass getTestClass() const{
return _testClass;
}
with
TestClass& getTestClass() {
return _testClass;
}
You want to return a reference otherwise you are just returning a copy of the variable. But Keep in mind that returning a (non-const) reference to the member variables of a class is not a good design approach.
Some things:
please don't use using namespace std; - read here why.
please don't name your variables _testClass - go with m_testClass instead. You can read hear about the reasoning.
You're returning a copy of _testClass. So when you modify it with setValue(89), nothing happens because you're only modifying a copy that is discarded at the end of the line. Instead, you should return a reference.
Change this here:
TestClass getTestClass() const{
To this:
TestClass &getTestClass() {
And you get the expected output.
Related
for some reason my prof insists I have to use setter/getter everywhere.
Well... in this linked list I don't understand why this one doesn't work
#include <iostream>
#include <string>
using namespace std;
class SomeClass{
string some_string;
public:
void setSomeString(string s);
string getSomeString();
};
void SomeClass::setSomeString(string s){
some_string = s;
}
string SomeClass::getSomeString(){
return some_string;
}
class Node{
SomeClass some_class;
Node *next;
public:
void setSomeClass(SomeClass sc);
SomeClass getSomeClass();
//...
};
void Node::setSomeClass(SomeClass sc){
some_class = sc;
}
SomeClass Node::getSomeClass(){
return some_class;
}
class List{
public:
Node *head, *ptr;
//...
};
int main(){
List l;
l.head = new Node();
l.head->getSomeClass().setSomeString("a string");
cout << l.head->getSomeClass().getSomeString();
return 0;
}
I expect in the output "a string", instead is empty... What am I doing wrong?
Node::getSomeClass() method returns something by value. This means that the returned object is a copy which means that now you have two different objects and there is no side effect.
If you want to edit the original value you need to return it by reference:
SomeClass& getSomeClass() {...}
In this way you will get the reference of the original object and you can edit it.
Don't wrap something if wrapper adds nothing to wrapped like SomeClass adds nothing to string except useless set/get.
Even if Node::getSomeClass() returns by reference why it's private in Node? If private member returned by reference it can be abused outside of Node.
If you insist to make SomeClass private in Node then l.head->getSomeClass().setSomeString("a string") should be l.head->setSomeString("a string") where:
void Node::setSomeString(string input){
some_class.setSomeString(input); //while not exposing some_class at all
}
I'm currently working on my first project using classes and objects, and I've run into a bit of a roadblock with my setter. I made up an example to illustrate the issue I'm running into (all one file for the sake of simplicity).
#include <stdio.h>
#include <iostream>
#include <string>
using namespace std;
class Example1
{
public:
Example1() { name = "Mike"; }
Example1(string aName) { name = aName; }
string GetName() const { return name; }
void SetName(string newName) { name = newName; }
private:
string name;
};
class Example2
{
public:
Example2() : anObj() {}
Example2(string aName) : anObj(aName) {}
Example1 GetObj() const { return anObj; }
void SetObj(string objName) { anObj.SetName(objName); }
private:
Example1 anObj;
};
int main()
{
Example2 myObj;
cout << myObj.GetObj().GetName() << endl;
myObj.GetObj().SetName("Stan");
cout << myObj.GetObj().GetName() << endl;
}
Output:
Mike
Mike
The idea is to alter the member object in Example2 by using the member object's setter method, but the setter method doesn't seem to be working the way I expected.
I tried accessing the member by moving it to public (in Example2) and using dot notation, and that successfully changed the name. I'm not sure what the differentiation is, but, since the getter is working properly, I feel like something is wrong with how I'm using the setter.
The original problem I was trying to solve was having a Game class with a Player class member object. The idea is that the player could change their name if they wanted to.
Appreciate any help. Thanks.
All your getters return a new object. Don't. Let them return a const &. But then you need a non const getter when you modify objects to call the setters:
const Example1& GetObj() const;
Example1& GetObj();
And now, the objects that are stored underneath will be updated, and not just their copies. Same for the strings.
You can also see the fact that the setters are not working on the proper objects by using a debugger.
I'm a student beginner in C++ (but yet have few hours on C), and I'm actually having a problem to use a pointer on my object. I really tried to find infos on the web, but it was pointless (pointless-pointer, do you get it ?!). So I try my luck here.
This code compiles now ! My apologies to all of you that try the code before that. Compiled with :
g++ -Wall -o exec main.cc
#include <iostream>
#include <vector>
//all the includes here
using namespace std;
class ExpLog
{
public:
virtual string toString() const=0;
//virtual int evaluate() const=0;
};
class Atom : public ExpLog
{
protected:
int value;
public:
Atom():value(0){}
string toString() const
{
return "a";//definition doesn't matter here
}
};
class ExpNot : public ExpLog
{
protected:
const ExpLog& opd;
public:
ExpNot(const Atom& a):opd(a){}
string toString() const
{
return "NOT"+opd.toString();
}
};
const ExpLog *my_function(vector<Atom> const& vect_atom, int i)
{
if(i>= vect_atom.size()) return NULL;
const Atom *a = &vect_atom[i] ;
if(i>0)
return a;
else{
ExpNot *n;
n = new ExpNot(*a);
cout<<n->toString()<<endl; //This line leads to a seg:fault
return n;
}
}
int main()
{
int i=-2;
vector<Atom> vect_atom(3);
my_function(vect_atom, i);
}
As others have said, this code snippet(s) does not compile in its current form. However, I'm willing to guess the problem is not in the line you have indicated, but the line
const Atom *a = &vect_atom[i]
If i > vect_atom.size() then this will point outside of the vector. Try adding a check for this just like you have a check for i < 0. If that check does match, then search up the for the root cause: the caller that is passing an invalid index.
I wonder if there is a workaround is such situation:
class A
{
class
{
public:
void setValue(int val) {i=val;}
private:
int i;
} B = initB(10);
std::function<decltype(B)(int)> initB = [this](int value)
{decltype(B) temp;
temp.setValue(value);
return temp;};
}
//...
A a; //crash
//...
I suppose it is caused by order of initialization. Variable B is initilized by calling an uninitilized std::function instance, hence the crash. By my logic, the workaround would be to initialize std::function first, then initialize member B. But then, such code is not valid:
class A
{
//error: 'B' was not declared in this scope
std::function<decltype(B)(int)> initB = [this](int value)
{decltype(B) temp;
temp.setValue(value);
return temp;};
class
{
public:
void setValue(int val) {i=val;}
private:
int i;
} B = initB(10);
}
I tried to make to make the std::function static, and such code works, but requires non-constexpr/const member, because std::function has non-trivial destructor - which is bad, because that requires source file, which requires creating such file, which requires some efford and destruction of my beautiful header-only class hierarchy! (I mean, I could be lazy and define this variable in the header, but then the multiple definition problem occurs). I know it might be a bad design (i'm just testing things out), but do you have any ideas how the problem can be solved without involving source files?
Although your example is contrived, there are times when I've needed (or its more convenient) to initialize complex objects in a similar way.
But, why use std::function<>? Why not just use a function?
class A
{
class
{
public:
void setValue(int val) { i = val; }
private:
int i;
} B = initB(10);
static decltype(B) initB(int value)
{
decltype(B) temp;
temp.setValue(value);
return temp;
}
};
Although, I wouldn't normally use decltype(B); I would just give the class a name.
I feel like I am somehow subverting your intent, but if you initialize the variables in the constructor, you can make things work.
#include <functional>
class A
{
class
{
public:
void setValue(int val) {i=val;}
private:
int i;
} B;
std::function<decltype(B)(int)> initB;
public:
A() {
initB = [this](int value)
{decltype(B) temp;
temp.setValue(value);
return temp;};
B = initB(10);
}
};
int main() {
A a;
}
A::initB is a value. It's not initialized at the point where you call it, because initialization is done (loosely speaking) in the order you specify member fields. You can verify this by executing the below, which works:
#include <iostream>
#include <functional>
using namespace std;
template<typename T, typename U>
T set(T& tgt, const U& src)
{
new(&tgt) T(src);
return tgt;
}
class A
{
class
{
public:
void setValue(int val) {i=val;}
private:
int i;
} B = set(initB, [this](int value)
{decltype(B) temp;
temp.setValue(value);
return temp;})(10);
std::function<decltype(B)(int)> initB;
};
int main() {
A a;
}
How to Define or Implement C# Property in ISO C++ ?
Assume following C# code :
int _id;
int ID
{
get { return _id; }
set { _id = value; }
}
I know C# convert the get and set lines to getXXX and setXXX methods in compile time. in C++ , programmers usually define these two function manually like :
int _id;
int getID() { return _id; }
void setID(int newID) { _id = newID; }
but, I want to have the C# syntax or a stuff like it in order to have a simple usability.
In C#, we can use properties like :
ID = 10; // calling set function
int CurrentID = ID; // calling get function
In C++, we can use our function like :
setID(10); // calling set function
int CurrentID = getID(); // calling get function
Now tell me how can I implement the C# properties in ISO C++.
thanks.
As Alexandre C. has already stated, it's very awkward and not really worth it, but to give an example of how you might do it.
template <typename TClass, typename TProperty>
class Property
{
private:
void (TClass::*m_fp_set)(TProperty value);
TProperty (TClass::*m_fp_get)();
TClass * m_class;
inline TProperty Get(void)
{
return (m_class->*m_fp_get)();
}
inline void Set(TProperty value)
{
(m_class->*m_fp_set)(value);
}
public:
Property()
{
m_class = NULL;
m_fp_set = NULL;
m_fp_set = NULL;
}
void Init(TClass* p_class, TProperty (TClass::*p_fp_get)(void), void (TClass::*p_fp_set)(TProperty))
{
m_class = p_class;
m_fp_set = p_fp_set;
m_fp_get = p_fp_get;
}
inline operator TProperty(void)
{
return this->Get();
}
inline TProperty operator=(TProperty value)
{
this->Set(value);
}
};
In your class where you wish to use it, you create a new field for the property, and you must call Init to pass your get/set methods to the property. (pref in .ctor).
class MyClass {
private:
int _id;
int getID() { return _id; }
void setID(int newID) { _id = newID; }
public:
Property<MyClass, int> Id;
MyClass() {
Id.Init(this, &MyClass::getID, &MyClass::setID);
}
};
Short answer: you can't.
Long answer: You could try to simulate them via proxy classes, but believe me this is not worth the minor incovenience in having set/get functions.
You'd have basically to define a class which forwards all the behavior of the variable. This is insanely hard to get right, and impossible to be made generic.
Quite simply. I'd argue this even has no overhead compared to making the variable public. However, you can't modify this any further. Unless, of course, you add two more template parameters that are call backs to functions to call when getting and setting.
template<typename TNDataType>
class CProperty
{
public:
typedef TNDataType TDDataType;
private:
TDDataType m_Value;
public:
inline TDDataType& operator=(const TDDataType& Value)
{
m_Value = Value;
return *this;
}
inline operator TDDataType&()
{
return m_Value;
}
};
EDIT: Don't make the call back functions template parameters, just data members that are constant and must be initialized in the constructor for the property. This inherently has greater overhead than simply writing a get and set method your self, because you're making function calls inside of your gets and sets this way. The callbacks will be set at run-time, not compile-time.