C++: writing a function for a struct outside that struct? [duplicate] - c++

This question already has answers here:
What are the differences between struct and class in C++?
(30 answers)
Closed 8 years ago.
For classes, you could just say:
class Test{
int a;
Test(int a);
}
Test::Test(int a) {
this->a=a;
}
Function names get "classname::" in front of them when declared outside of class.
How would I do this for structs?
struct Test {
int a;
Test(int a);
}
How would I write the function for this struct Test outside of struct declaration so that it can be only be called by a Test struct?

Same way. Difference between struct and class in C++ is only default visibility of members (private for class, public for struct).
Actually, it's not just function, it's constructor of class/struct Test.

In C++, structs are essentially the same as classes except for their default protection levels: classes default to private, structs to public. To define that function outside of the struct so that it can only be called from a member, declare it as private, then define it as normal:
struct Test {
private:
int a;
Test(int a);
};
Test::Test(int a) {
this->a=a;
}
Additionally, instead of modifying the a member in the constructor body like that, you should use an initializer list. This sets the value of the member before the instance is fully constructed. It's not so important with just an int, but it's a good practice to get in to.
struct Test {
private:
Test(int a) : a(a) {}
int a;
};

How would I write the function for this struct Test outside of struct declaration
Do exactly what you did for the first one. Both are class types, whether you use the class or struct keyword to introduce them.
The only difference is the default accessibility of members and base classes: private if you use class, and public if you use struct.
so that it can be only be called by a Test struct?
If you mean that you want it to be private (as it is in the first example), then you'll have to do so explicitly, since accessibility defaults to public:
struct Test {
int a;
private:
Test(int a);
};
Personally, I'd use the more conventional class if there's anything non-public.

ForEveR is right. Just like in the question you can have a structure member defined like:
struct Test{
int a;
Test(int a);
};
Test::Test(int a) {
this->a=a;
}
point to note, struct members are public by default. class memebers are private by default.

Related

friend function pointer parameter in constructor

i'm trying to create a costructor in the form
class A {
public:
A(void (*initializer)(A&))
{
initializer(*this);
}
};
where initializer take a reference to the instance he's passed and can make custom operation on variable it is initializing. Is there a way to make such a function friend so it can access to private variables too?
Here is a simple way:
class Impl
{
public:
int x;
int y;
};
class A
{
public:
A(void (*initializer)(Impl&))
{
initializer(_impl);
}
private:
Impl _impl;
};
This hides _impl from everyone except initializer. And since nobody other than initializer can access _impl at all, the members of of class Impl can be public, making it easy for initializer to mutate them.
Other than listing all the functions you want to pass pointers to as friends separately, no. An alternative may be to separate the data into a base class with public members you inherit privately from:
struct AData
{
int m_privateInt;
...
};
class A : private AData {
public:
A(void (*initializer)(AData&))
{
initializer(*this);
}
};
You may need to also pass a reference to A, if you want to access its member functions in initializer.

clarification of initialization in C++

I am really getting confused in following examples:
#include <iostream>
class C {
public:
int a,b;
};
int main() {
C c{3,6};
std::cout<<c.a<<'\n';
std::cout<<c.b<<'\n';
return 0;
}
It works fine and gives the expected outcome. But if I modify the above code like below.
#include <iostream>
class C {
int a,b;
public:
int get_a(){
return a;
}
int get_b(){
return b;
}
};
int main(){
C c{3,6};
std::cout<<c.get_a()<<'\n';
std::cout<<c.get_b()<<'\n';
return 0;
}
In the above program compiler shows multiple errors. Why uniform initialization allowed in first program but not in second? Where I am wrong?
By default c++ class members are private, so without specifying you get a private variable. Because you made the types private you do not get the aggregate-initialization for free anymore so you need to write your own constructor for this class:
class C{
C(int _a, int _b):
a(_a), b(_b)
{}
};
You just need to fix the namespacing for the cout and your code should compile fine: http://coliru.stacked-crooked.com/a/1d69f4f141d2bcd2
From the standard:
[dcl.init.aggr] An aggregate is an array or a class with no user-provided constructors, no brace-or-equal-initializers for non-static data members, no private or protected non-static data members, no base classes, and no virtual functions
In the first code you only had public variables so the code worked because you had an aggregate, making the variable private is what caused the problem because it was no longer an aggregate according to the above definition.
a and b are private in your second example and are therefore inaccessible from outside the class.
You need to move the line int a,b; into the public: scope like the first example.
You also need std:: in front of cout
#include <iostream>
class C {
public:
int a,b; //Make public
int get_a(){
return a;
}
int get_b(){
return b;
}
};
int main(){
C c{3,6};
std::cout<<c.get_a()<<'\n'; //use namespace std::
std::cout<<c.get_b()<<'\n'; //use namespace std::
return 0;
}
In the modified version of the code, you moved the public: label so the a and b data members are no longer public. Hence, they cannot be referenced from outside the class, even not implicitly by an initializer list.
The first code worked because the data members a and b were public, so they could be accessed from outside the class. However, in the second code, they are declared as private, so they cannot be accessed from outside the class. Either declare them as public again, or use a constructor as follows (if you still want them as private):
C(int x,int y) // This is a parameterised constructor
{
a=x;
b=y;
}
And initialise them as C c(3,6);

C++ Invalid use of non-static data member

I wanted to pass-in functions as arguments to a templated function without having any indirection. To achieve this I created two nested structs, each defining the function I wish to pass in to the templated function. Each of the structs accesses data members from the outside class B:
namespace A{
class B{
public:
B();
template <typename T>
void templatedFunction(T t){
//I pass one of the struct objects in to here, to invoke the desired function
t();
}
private:
struct X{
void operator(){
do();
}
void do(){
//Accesses the data members of class B
e->doSomething();
}
};
struct Y{
void operator(){
do();
}
void do(){
//Accesses the data members of class B
d.doSomething();
}
};
C* c;
D d;
E* e;
};
}
and the compiler errors I get are pretty much all of the format:
error: invalid use of non-static data member B::d
for the lines within the struct accessing the class data members and on the lines declaring the data members in B.
A nested class in C++ does not (automatically) have access to an instance of the containing class. It's just a class definition like any other. You need a B instance to access non-static data members of B.
You can restructure your nested class Y as
struct Y
{
void operator()( B& b ){
do( b );
}
void do( B& b ){
//Accesses the data members of class B
b.d.doSomething();
}
};
and fix your function template and calls, and class X, accordingly.
Note that your presented code for operator(), with no argument list, would not have compiled, but I'm not downvoting since you are stopped by another compilation error (i.e., possibly it is the real code you're showing).
If you have a struct (or class for that matter) nested in another class, it it not treated specially in any way. It works exactly the same as if the struct was defined outside of the enclosing class. The only thing which is different is the scope of nested class name. So, if you have
class A { class B{}; };
and
class B{}; class A {};
the only difference is that outside class A you need to name the class B as A::B in the first case, and just B in the second class. There is no other difference, and in particular class B does not gain any special access to class A members.

Accessing Class Data from Declared Struct

Alright, so I've tried a few ways to deal with this issue, but I can't seem to fix it.
In my header file I have:
class MyClass {
public:
bool test;
struct MyStruct;
};
I also have a constructor and all that, but that's not the important/not causing errors
In the cpp what I want to do is this:
MyClass::MyStruct {
test=true;
};
The problem with this, is that the struct is unable to access the test variable. How can I pass the current instance's variable to the struct or some other way to allow the struct to access the variable.
This:
MyClass::MyStruct {
test=true;
};
Is not at all valid C++ code. Perhaps you meant this:
MyClass::Class() {
test=true;
}
Which would make a default constructor of MyClass which sets test to true. But your question makes it seem like you want to set the value of MyClass::test from MyClass::MyStruct. This is not really possible, because a nested class (or struct, in your case) does not "inherit" or "contain" or really have almost any special relationship with its enclosing class (or struct).
Another possibility is this:
class MyClass {
public:
static bool test;
struct MyStruct;
};
MyClass::MyStruct::MyStruct() {
test=true;
}
Which would make a default constructor of the nested struct which sets a variable in the enclosing class, but the variable then needs to be static, meaning there's only one in the whole program, not a separate value per instance of either class or struct.
Seems to me if MyStruct is executing code it should be a class. And if so, you either pass it an instance of the MyClass (e.g. this if calling from MyClass), or pass it a reference to the member it needs (e.g. this->test)...
You can declare the structure as a friend in the class definition.
class MyClass {
public:
bool test;
friend struct MyStruct;
};
Edit:
class MyClass {
friend class MyStruct(MyClass *myClass) : myClass(myClass) {
private:
MyClass *myClass;
}
MyStruct *myStruct;
bool test;
public:
MyClass() {
myStruct = new MyStruct(this);
}
}
Note: This is untested and just written in my browser. I know it's missing destructors and stuff.
Since you're passing the parent pointer to the member class, the member class can then access the parent class's private members because it was declared a friend.

How can I have class within struct

I have a class..
class myClass
{
public:
myClass(int time);
}
Then I need to have this class within struct.
class TopClass
{
public:
typedef struct{
int myint;
myClass myclass;
}tStruct;
tStruct sStruct1;
tStruct sStruct2;
}
How can I do it? How can I call constructors for myClass?
Is only way to use class instead of struct?
My constructor
TopClass::TopClass():
sStruct1({32, myClass(100)}),
sStruct2({52, myClass(1000)})
{
}
But I am getting error:
extended initializer lists only available with -std=c++0x or -std=gnu++0x
You can add constructor to struct: http://ideone.com/ifBw2
class TopClass
{
public:
struct tStruct {
tStruct(int time, int k = 0): myint(k), myclass(time) {}
int myint;
myClass myclass;
};
TopClass(int t): sStruct1(t), sStruct2(t) {}
tStruct sStruct1;
tStruct sStruct2;
};
Edit
As for new question - you have to use new standard (-std=c++0x) to do that this way. In old standard you have to add explicit ctor to initialize member variables. struct in C++ is nearly exactly the same as class - you can add ctors, member functions, static functions. The only difference is default privacy - public for struct and private for class:
class A {
public:
int b;
};
is exactly the same as
struct A {
int b;
};
How can I do it? How can I call constructors for myClass?
Your struct will need a constructor, since it has a member with no default constructor. In order to have a constructor, it will also need its own name, not just a typedef alias.
struct tStruct {
// If you want a default constructor:
tStruct() : myClass(42) {}
// If you want to specify the time:
tStruct(int time) : myClass(time) {}
int myint;
myClass myclass;
};
Is only way to use class instead of struct?
class and struct mean exactly the same thing (apart from the minor distinction of having different default access specifiers). Anything you can do with one, you can do with the other.
Actually, Pawel Zubrycki’s answer is all right.
But I want to know why you have to do in this way that you have to import another class constructor inside TopClass.
I mean that the code should follow the rule of high cohesion and low coupling.
In software construction we’d rather prefer the composition (an important design mode) to a class defination in it. Something like the following code.
class B{
public:
B(int y){b = y;}
private:
int b;
};
class A {
public:
A(int x):b(x){...};
private:
B b;
};
From the code we can maximize class B and obviously reduce the complexity of class A. A & B can change all by themselves.