I have the following code:
#include <iostream>
class First {
public:
Second* x;
void make_value(Second* sec_);
First() {
// Initialization
}
};
class Second {
public:
First* y;
Second() {
// Initialization
}
};
void First::make_value(Second* sec_) {
x = sec_;
}
void main() {
fir = new First();
sec = new Second();
fir->make_value(sec);
}
The two classes each have a member variable of the other class, which does not work for obvious reasons.
My question is whether or not there is a way to late-initialize variable x after class Second has been initialized. If not, what alternatives are there?
For any uses where the compiler doesn't need the definition of a class, a forward declaration will suffice. Pointers and references to types do not require a definition.
class Second; // forward declare
class First {
public:
Second* x;
void make_value(Second* sec_);
First() {
// Initialization
}
};
class Second {
public:
First* y;
Second() {
// Initialization
}
};
void First::make_value(Second* sec_) {
x = sec_;
}
Related
Assuming I have these classes (question marks mark the question what I need to pass here):
class A
{
...
public:
void pass()
{
B ins;
ins.doSth(?????);
}
};
class B
{
...
public:
void doSth(const A &sth)
{
...
}
}
int main()
{
A te;
te.pass();
}
Can you pass an instance of your own class or is this just an example of a failed class structure on my side?
The current object in a member function is *this. You can pass that to another function.
You will have to consider how the classes depend on each other, and that one class cannot use the other class until the declaration is complete.
This would work though:
class A
{
//...
public:
void pass();
};
class B
{
//...
public:
void doSth(const A &sth)
{
//...
}
};
// Here both classes are completely declared
void A::pass()
{
B ins;
ins.doSth(*this);
}
int main()
{
A te;
te.pass();
}
Your class "contains" an instance of each other so you'll face an error of undeclared types. To solve this issue you need to use forward declaration.
And you'll face another problem:
If your methods doSth() and pass() are defined inlinlely then you'll face a problem: "using incomplete types". The workaround this is to implement these methods outside the class so that each object has been fully constructed before used.
The program may look like:
class A;
class B;
class A{
public:
void pass();
};
class B{
public:
void doSth(const A &sth){
}
};
void A::pass(){
B ins;
ins.doSth(*this);
}
int main(){
A te;
te.pass();
return 0;
}
I am super-new to classes and still wrapping my brain around how they work. Any help/advice/pointers-> are appreciated!
I have two classes. Within the second class is an array of the first class. I am trying to assign values to the private member variables contained in the array of the first class.
I get this error message when compiling:
hw2Test.cpp: In member function 'void bar::set(int)':
hw2Test.cpp:11:7: error: 'int foo::x' is private
int x;
^
hw2Test.cpp:34:12: error: within this context
foodoo[0].x = x;
^
Here is the code:
#include <iostream>
using namespace std;
class foo
{
public:
private:
int x;
};
class bar
{
public:
void set(int x);
private:
foo foodoo[1];
};
int main()
{
bar tar;
tar.set(1);
return 0;
}
void bar::set(int x)
{
foodoo[0].x = x;
}
foo::x is declared as private, so only methods of foo can access it. But you are trying to access x inside of a method of bar instead, which does not have access to foo's private members.
To give bar access, you need to either:
declare foo::x as public:
class foo
{
public:
int x;
};
void bar::set(int x)
{
foodoo[0].x = x;
}
declare a public setter:
class foo
{
public:
void set(int i);
private:
int x;
};
void foo::set(int i)
{
foodoo[0].x = i;
}
void bar::set(int x)
{
foodoo[0].set(x);
}
declare bar as a friend of foo:
class foo
{
public:
private:
int x;
friend class bar;
};
void bar::set(int x)
{
foodoo[0].x = x;
}
Here is the idea: I have a class that has some member variable(s), say x. This class also has a method, A(), which does not modify the member variable(s), but returns info about them. There is also a method B() which does modify the member variable(s). So basically, this is the setup:
class Class
{
int x;
Class(int x) : x(x) { }
int A() { return x; /* info about x */ }
void B() { x++; /* updates x! */ }
}
So far so good. But now I want to have some special version of this class that will be used throughout the project, and I want it to have a specific set of member variable(s), say, x = 3. My idea was to add a const static Class mySpecialCase member to Class, and just refer to Class::mySpecialCase whenever necessary.
The problem however, is that I need to call A() on this object, to fetch some information, but do not want B() to be called on this object, since it would modify x, which would affect all future usage of the 'special case'.
Any ideas on how to solve this?
It's already illegal to call Class::mySpecialCase.B(), since mySpecialCase is const and B() is not a const member. You just need to make it possible to call A(), by making A() a const member function:
class Class
{
int x;
public:
Class(int x) : x(x) { }
static const Class mySpecialCase;
int A() const { return x; /* info about x */ }
void B() { x++; /* updates x! */ }
};
// In class.cpp:
const Class Class::mySpecialCase{3};
The problem however, is that I need to call A() on this object, to fetch some information, but do not want B() to be called on this object, since it would modify x,
Declare the object and B() as const but not A():
class Class {
public:
[...]
int A();
void B() const;
};
// Initialize const object.
const Class specialCase(3);
Calling specialCase.A() will be a compile error, but specialCase.B() is still okay because the const modifier indicates to the compiler this method does not alter the object.
So far so good.
Not really. A should be const:
int A() const { return x; /* info about x */ }
But now I want to have some special version of this class
By version, you mean instance, right?
Add a static member function returning a reference to a static local instance of Class:
#include <iostream>
class Class
{
public:
int x;
Class(int x) : x(x) { }
int A() const { return x; /* info about x */ }
void B() { x++; /* updates x! */ }
static Class &SpecialInstance()
{
static Class instance(3);
return instance;
}
};
int main()
{
Class a(1);
Class b(2);
Class c = Class::SpecialInstance();
std::cout << c.A() << "\n";
}
Please check the following code. Why it is wrong and how to fix? Thank you.
class A
{
public:
class B
{
public:
B(int(*cf)())
{
f = cf;
}
int (*f)();
};
B *b;
A()
{
b = new B(this->a);
}
int a()
{
}
};
int main()
{
A a;
}
compilation error:
If you absolutely need to call a function by pointer you will need to use a pointer to member function instead of a pointer to function. A pointer to member function has a different declaration syntax that includes the class type the function belongs to. In your case the parameter declaration would look like int (A::*cp)(). You will also need to change the declaration of the f member variable to int (A::*f)().
In order to call a pointer to member function you need to have a pointer to an object of the type the function belongs to. You also need to use one of the pointer to member operators; ->* or .*
void call(A* c, int (A::*f)())
{
(c->*f)(); // call member function through pointer
}
The extra set of parenthesis is required due to the order of precedence of operators.
The following code includes the changes necessary for you to use pointer to member functions.
class A
{
public:
class B
{
public:
// Take a pointer to member function.
B(int(A::*cf)())
{
f = cf;
}
void call(A* c)
{
(c->*f)();
}
int (A::*f)(); // pointer to member function
};
B *b;
A()
{
b = new B(&A::a);
}
int a()
{
return 0;
}
};
int main()
{
A a;
a.b->call(&a);
}
I also recommend that you consider using std::function and std::bind (or their Boost equivalents if you do not have a C++11 compiler).
Do not use function pointers in the first place when using C++.
There is an easier and more elagant solution - an interface.
i.e.
class Interface {
public:
virtual int CallMe() = 0;
};
class B : public Interface { int CallMe() { return 5; };
class A : public Interface {
private:
Interface *m_i = 0;
public:
A(Interface *i) : m_i(i) { }
A() : m_i(this) { };
void DoIt() { cout << m_i->CallMe() << endl; }
int CallMe() { return 8; }
};
int main() {
A a(new B); // Coult be any object that implements Interface (as yes it is a memory leak
A aa();
a.DoIt(); // Will print 5
aa.DoIt(); // WIll print 8
return 0;
}
I am trying to deal with friend class for the first time. I wrote the code below:
class Kind{
private:
friend class Type;
int x;
public:
Kind(){ x=0; }
void setX(int X) { x =X; }
int getX() { return x; }
};
class Type: public Kind {
public:
friend class Kind;
Type(){ }
Kind root;
root.x=3;
};
The compiler tells me that I can not do root.x=3;, What is the problem??
The problem is your trying to execute a statement in a place where the compiler is expecting member declarations. Try putting it into a method
class Type : public Kind {
...
void Example() {
Kind root;
root.x = 3;
}
};
You cannot do the assignment as part of the class declaration. Do it in a member function instead.