use the member pointer via a Get function and allocate memory outside, not clear why in this way
-
hi guys probably already discussed but I did not find the explenation: in the above code: My question is why I have to use reference to the pointer when returning from mGetPt? If this pointer whould have been used inside the function, and for example used in constructor to allocate memory if I have an Get function like CInner* mGetPt(void) I am able to use the pointer as I want. but in the above example it is required to return a reference. (this is the return value, is not a function param; OK I know in case of function params I have to use reference to pinter) Please someone clarify me why?
class CInner
{
public:
int mx;CInner() { mx=1; }
};
class CTest
{
private:
CInner *pt;public:
CTest()
{
pt= NULL;
}CInner\*& mGetPt(void) { return pt; }
};
int _tmain(int argc, _TCHAR* argv[])
{
CTest *obj= new CTest();obj->mGetPt() = new CInner(); cout<<obj->mGetPt()->mx; cin.get(); return 0;
}
-
hi guys probably already discussed but I did not find the explenation: in the above code: My question is why I have to use reference to the pointer when returning from mGetPt? If this pointer whould have been used inside the function, and for example used in constructor to allocate memory if I have an Get function like CInner* mGetPt(void) I am able to use the pointer as I want. but in the above example it is required to return a reference. (this is the return value, is not a function param; OK I know in case of function params I have to use reference to pinter) Please someone clarify me why?
class CInner
{
public:
int mx;CInner() { mx=1; }
};
class CTest
{
private:
CInner *pt;public:
CTest()
{
pt= NULL;
}CInner\*& mGetPt(void) { return pt; }
};
int _tmain(int argc, _TCHAR* argv[])
{
CTest *obj= new CTest();obj->mGetPt() = new CInner(); cout<<obj->mGetPt()->mx; cin.get(); return 0;
}
You need to return a reference to the pointer if you want an outsider to be able to change the value of that pointer. It looks like an ugly attempt to make dependency injection. A setter/getter would IMO be clearer. Who's responsible for deallocating the instance? The contract isn't clear at all. If trying something like that, a massive comment block describing responsibilities would be a minimum.
-
hi guys probably already discussed but I did not find the explenation: in the above code: My question is why I have to use reference to the pointer when returning from mGetPt? If this pointer whould have been used inside the function, and for example used in constructor to allocate memory if I have an Get function like CInner* mGetPt(void) I am able to use the pointer as I want. but in the above example it is required to return a reference. (this is the return value, is not a function param; OK I know in case of function params I have to use reference to pinter) Please someone clarify me why?
class CInner
{
public:
int mx;CInner() { mx=1; }
};
class CTest
{
private:
CInner *pt;public:
CTest()
{
pt= NULL;
}CInner\*& mGetPt(void) { return pt; }
};
int _tmain(int argc, _TCHAR* argv[])
{
CTest *obj= new CTest();obj->mGetPt() = new CInner(); cout<<obj->mGetPt()->mx; cin.get(); return 0;
}
Firstly, I agree with Niklas, this is terrible style and structure. A class should be responsible for allocating and deallocating all its memory. To answer your question, returning a pointer allows you to modify the data that is pointed to (in your case this is NULL, so it would result in an access violation). Returning a reference allows you to modify the value of the original variable returned (think of reference as "another name for the variable X") So, in order to modify the value of the variable
pt
rather than the data it points to, you can either return a reference to the variable, or a pointer to the variable itself. You are returning the reference, to return a pointer you would use it like://class CTest
CInner** mGetPt(void) {
return &pt;
}//_tmain()
*obj->mGetPt() = new CInner();Having said that, this is still bad style, and you would be much better off with something like:
class CInner {
public:
CInner() : mx(1) { } //This is an initialiser list, and is equivalent to "mx = 1". This is quicker and cleaner than using "mx = 1"
int GetMX() { return mx; }
void SetMX(int nNewMx) { mx = nNewMx; } //This allows you to validate the value getting set, and is good style even if you don't need to validate itprivate: int mx; //It is good style to have variables as private, or protected, then have a get/set function which can validate the value
};
For
CTest
you have 2 choices, you can either allocatept = new CInner
in the constructor or when it is needed.//Preallocate solution
class CTest {
public:
CTest() : pt(new CInner) { } //Allocate in the constructor
~CTest() {
if (pt != NULL) {
delete pt; //Don't forget to delete the memory
}
}
CInner *mGetPt() { return pt; } //Don't return by reference, it is bad styleprivate: CInner \*pt;
};
//Allocate on demand solution
class CTest {
public:
CTest() : pt(NULL) { } //Set to NULL
~CTest() {
if (pt != NULL) {
delete pt; //Don't forget to delete the memory
}
}
CInner *mGetPt() { //Don't return by reference, it is bad style
if (pt == NULL) {
pt = new CInner;
}
return pt;
}private: CInner \*pt;
};
You can then use it like:
int _tmain(int argc, TCHAR *argv[]) {
CTest *obj = new CTest();
cout << obj->mGetPt()->GetMX();
cin.get();
return 0;
}