I have a problem with a pointer defined in an nested class 'Outer::Inner' to a member function of the 'Outer' class:
class Outer{
//class Inner;
class Inner{
public:
Inner(Outer& o){
}
int (Outer::*pf)(int);
};
public:
Outer();
~Outer();
int function(int a);
Inner* i;
};
Outer::Outer(){
i = new Inner( *this );
i->pf= &Outer::function;
(i->*pf)(2); //problem here!
};
Outer::~Outer(){
delete i;
};
int Outer::function(int a){
return 0;
};
As you can see I would like to call the function through the pointer of the Inner class but I get an error: 'pf' was not declared in this scope.
As the error says, pf is not declared in that scope. It's a member of i, accessible as i->pf. Presumably, you want to call it on this:
(this->*(i->pf))(2);
You need to call the function "on" some Outer object, as it's a pointer to a member function.
Looking at your code, maybe you need this
//-----------------vvv <- argument
(this->*(i->pf))(2);
//-^--------------^ <- these are important and they say something like
// "execute function `*(i->pf)` on `this` object"
2 solutions.
1: (pointer to non-member function)
class Outer{
class Inner{
public:
Inner(Outer& o){
}
int (*pf)(int);
};
public:
Outer();
~Outer();
static int function(int a);
Inner* i;
};
Outer::Outer(){
i = new Inner( *this );
i->pf= &Outer::function;
int j = (*(i->pf))(2); // now OK
};
2: (pointer to member function, has to be called on some instance's)
class Outer{
class Inner{
public:
Inner(Outer& o){
}
int (Outer::*pf)(int);
};
public:
Outer();
~Outer();
int function(int a);
Inner* i;
};
Outer::Outer(){
i = new Inner( *this );
i->pf= &Outer::function;
int j = (this->*(i->pf))(2); // now OK
};
Related
How do I change the int 'a' inside class A but restrict the function that changes the int to ONLY class B? I do not even want A to be able to change it.
I have tried to create a friend function, but I get an error I included in the comments of the code. I then tried to just forward declare the function as a friend function in private and then actually creating the function in public, but the C class can access the public function. This despite me writing (in the private section) that the function is a friend function. Can I 'friend' a private value? I am unsure what to do here.
#include <stdio.h>
#include <iostream>
int main() {
// forward declaration
class B;
class C;
class A {
private:
int a; // private member I want to edit, but only via class B.
int a2; // I would like to NOT be able to access this in class B. I only want to access and modify int a from class B, no other variable. If possible.
// invalid use of non-static data member 'a'
friend void test(int new_value) {
a = 5;
}
friend B;
public:
};
class B {
private:
int b;
public:
change_a_value(A a_class, int new_int) {
a_class.test(new_int); // I want this to be possible.
}
};
class C {
private:
int c;
public:
change_a_value(A a_class, int new_int) {
a_class.test(new_int); // I want this to be impossible
}
};
return 0;
}
Add "void" before prototypes of change_a_value, and change the
friend B
to
friend class B
and suppress friend in
friend void test(int new_value) {
complete corrected program :
int main() {
// forward declaration
class B;
class C;
class A {
private:
int a; // private member I want to edit, but only via class B.
int a2; // I would like to NOT be able to access this in class B. I only want to access and modify int a from class B, no other variable. If possible.
void test(int new_value) {
a = new_value;
}
friend class B;
public:
};
class B {
private:
int b;
public:
void change_a_value(A a_class, int new_int) {
a_class.test(new_int); // I want this to be possible.
}
};
class C {
private:
int c;
public:
void change_a_value(A a_class, int new_int) {
a_class.test(new_int); // I want this to be impossible
}
};
return 0;
}
Compilation results are what was expected :
TestCpp2.cpp:9:14: error: ‘void main()::A::test(int)’ is private
void test(int new_value) {
^
TestCpp2.cpp:28:31: error: within this context
a_class.test(new_int); // I want this to be impossible
^
Makefile:510: recipe for target 'TestCpp2.o' failed
make: *** [TestCpp2.o] Error 1
Suppose I have a class Foo which has a member variable of type std::vector<Bar>:
class Foo;
class Bar
{
public:
int x;
Foo* parent;
void trigger(size_t i);
};
class Foo
{
public:
std::vector<Bar> arr;
void moveBack(size_t i);
};
void Bar::trigger(size_t i)
{
parent->moveBack(i);
}
void Foo::moveBack(size_t i)
{
std::swap(arr[i], arr[arr.size()-1]);
}
int main()
{
//...Init foo of type Foo and fill the arr
foo.arr[3].trigger(3);
}
I am wondering if the code above is dangerous or undefined behaviour. Essentially the object of type Bar is moving itself.
Edit: Added forward declaration
How to pass member of pointer to template argument?
It is hard to explain, so I will show a very short code to indicate the problem.
This is a valid code :-
template<class T, int T::*a> class B{...}
class A{ public: int mem; }
int main(){
A a;
B<A,&A::mem> b= B<A,&A::mem>(a); // I pass "A" as value
}
Now I want to pass pointer instead of value as followed :-
template<class T, int T::*a> class B{...}
class A{ public: int mem; }
int main(){
A* a=new A(); //changed
B<A*,&A*::mem> b= B<A*,&A*::mem>(a); //changed, pass "A*" (#)
}
This is a compile error that I got.
prog.cpp:18:13: error: template argument 2 is invalid
B<A*,&A*::mem> b=B<A*,&A*::mem>(a);
^
I am wrong at the line (#). How should I edit the line?
Edit
Here this is the full code :-
class A{
public: int x=2;
};
template <class T, int T::*a> class B{
T objectA_;
public: B(T objectA){
objectA_ = objectA;
}
public: void print(){
std::cout<< objectA_.*a ;
}
};
int main() {
A objectA; objectA.x=3;
B<A,&A::x> objectB=B<A,&A::x>(objectA); //this line will be changed
objectB.print(); //print 3
return 0;
}
Notice that T=A.
Now, I want T=A*.
new version
template <class T, int A::*a> class B{
T objectA_;
public: B(T objectA){
objectA_ = objectA;
}
public: void print(){
std::cout<< objectA_->*a ; //changed
}
};
int main() {
A* objectA = new A(); objectA->x=3; //changed
B<A*,&A*::x> objectB=B<A*,&A*::x>(objectA); //changed
objectB.print();
delete objectA; //new
return 0;
}
B<A, &A::mem> is still the correct form. What you need to change is the class definition.
template<class T, int T::*a>
class B
{
T *object_;
public:
B (T* pObj) : object_(pObj) {}
};
But if you have access to a smart pointer implementation (c++11 or other) prefer to store that instead of the raw pointer. If you do not, you'll have to abide to the rule of three (now rule of five in c++11).
Also, you can simplify your life a whole lot if you do value initialization instead of copy initialization.
B<A, &A::mem> b(a);
B<A, &A::mem> b(&a);
Is it possible to achieve this code?
class apple;
class fruit{
public: int i;
void set(apple a){
}
};
class apple{
public: int j;
void set(fruit f){
}
};
I know this leads to error: 'a' has incomplete type. even I interchange classes, It always leads to incomplete type error. I have a question can this be achieved? Iam not sure. any help is greatly apprciated. Thanks
Update
class apple;
class fruit{
public: int i;
void set(apple* a);
};
class apple{
public: int j;
void set(fruit f){
}
};
void fruit::set(apple *a){
apple b = *a;
}
I Guess this workaround works. but is there any other solution?
It's possible, but you need to have method definitions outside of the class:
class apple;
class fruit {
public:
int i;
void set(apple a);
};
class apple {
public:
int j;
void set(fruit f);
};
void fruit::set(apple a)
{
i = a.j;
}
void apple::set(fruit f)
{
j = f.i;
}
Using pointers or references, since only the name needs to be known in that case:
class apple;
class fruit{
public:
int i;
void set(apple* a); // OK
void set(apple& a); // Also OK
};
And you need to move the implementation of the function to a place where the definition of apple is known.
You cannot have a circular reference like this. Only possibility is to have a pointer to object used instead of object, as in:
class apple;
class fruit{
public: int i;
void set(apple * a){
}
};
class apple{
public: int j;
void set(fruit * f){
}
};
and manage with de-referenced object within the functions, i.e. use *f within the implementation of these functions apple::set and fruit::set
If you would like to have the object non-modifiable when you pass as a pointer, use as:
class apple;
class fruit{
public: int i;
void set(const apple * a){
}
};
class apple{
public: int j;
void set(const fruit * f){
}
};
I'm currently reading C++ Primer and am at the point of class friends and member function friends and I'm having trouble figuring out how to get the code that has the following pseudoform to work:
class B;
class A {
public:
A(int i): someNum(i) { }
private:
int someNum;
friend void B::someMemberFunction(Args); // Compile error: Incomplete Type
};
class B {
public:
void someMemberFunction(Args) { /* doStuff */ }
private:
vector<A> someVector { A(5) };
};
If you try to compile in this form it gives the incomplete type error on the friend line. So the solution is to move the class B definition above class A:
class A;
class B {
public:
void someMemberFunction(Args) { /* doStuff */ }
private:
vector<A> someVector { A(5) }; // Compile error: Incomplete Type
};
class A {
public:
A(int i): someNum(i) { }
private:
int someNum;
friend void B::someMemberFunction(Args);
};
However now on the vector line, it doesn't know how to create an object of type A, since A has yet to be defined. So then A needs to be defined before B. But now we've arrived back at the original problem. I think this is called circular dependency? I don't know how to fix this with forward declarations.
Any help would be appreciated. Thanks.
I think you will either have to make the whole of class B a friend (which removes a dependency in A anyway so it's probably a good thing), or use a constructor instead of the in-class initializer.
class B;
class A {
public:
A(int i): someNum(i) { }
private:
int someNum;
friend class B;
};
class B {
public:
void someMemberFunction() { /* doStuff */ }
private:
vector<A> someVector { A(5) };
};
Or this
class A;
class B {
public:
B();
void someMemberFunction() { /* doStuff */ }
private:
vector<A> someVector;
};
class A {
public:
A(int i): someNum(i) { }
private:
int someNum;
friend void B::someMemberFunction();
};
B::B(): someVector{A(5)} { }