Syntax for class within a class in C++ - c++

If I have the following
class A
{
public:
int stuff;
void helper(B temp, int d); //what about here? I'm getting a 'B' has not been declared error here.
private:
class B
{
public:
int stuffer;
private:
int x;
};
}:
Whats the correct way to refer to class 2 in my implementation file? Would it be
1::2::someMethod? Or 2::someMethod?

Assuming that 1 and 2 refer to REAL class names, 1::2::methodName just like any other nested scoping.

First of all, class name cannot start with integer. So renaming them:
class A
{
public:
int stuff;
private:
class B
{
public:
int stuffer;
private:
int x;
};
};
Second, since the nested class B is in the private section, so you cannot access it from outside the scope of class A. B is accessible to A only. And the syntax of declaring an object of type B would be B bObj; in the scope of A.
Now you should try yourself first, before asking futher questions!
As for your edit (the added question): it's not compiling because by the time the compiler sees B temp, it has not yet seen the definition of B, that is why it says B is not declared!
The fix is very simple. Declare B before it's used, something like this:
class A
{
private:
class B
{
public:
int stuffer;
private:
int x;
};
public:
int stuff;
void helper(B temp, int d);
}; //<--- this is also fixed. your code has 'colon', instead semi-colon!
Also read the comment at the end of the class!

If you're inside a method of class 1, you can use 2::somemethod. In other places, use 1::2::somemethod. "Inside" includes method argument declarations in method implementations of class 1, but not return value declarations for method implementations of class 1.

It depends on which scope level you're at. Inside a member function for class 1, it would be class_2::someMethod. At file scope, it would be class_1::class_2::someMethod. It's always correct to fully qualify a function or variable name like that, but sometimes it's more typing than is strictly necessary. In general, you need the scope resolution operator :: when the compiler can't figure out on its own what you're referring to.
In practice, the best way to find out is try it and see what happens. If the compiler gives you an error, throw the class name in front of it and try again.

Syntax for nested class:
Class class_name1
{
Private:
Data members
Public:
Member functions
{
.........
}
Class class_name2 //class2 is embedded with class1
{
Private:
Data members
Public:
Member functions
{
.........
}
}; // class2
}; //class1
Nested class is possible to define one class within another class since a class declaration does,define a scope.
A nested class is valid only within the scope of the enclosing class.
Need of nested class is virtually not existed.

Related

Class Pointer reference inside of another Class defined below? (C++ 14, VS 2019)

Problem Summary
I'm attempting to write a series of classes in C++ 14, that are all supposed to be inside of the same class, and have pointer fields that point to object instances of each one of the classes. They are all also supposed to have constructors that assign those fields, using arguments that are pointers to the other class instances. I'm running into a problem where I am unable to call the constructor with the pointer arguments. Below is an illustration of my problem:
Defined in header file:
class A;
class B;
class C;
class A {
public:
class B {
public:
B(C* arg) {
ptr = arg;
}
C* ptr;
};
class C {
public:
...
};
};
Runner code in cpp file:
A::C TEST_C = *new A::C();
A::B TEST_B = *new A::B(&TEST_C);
The line which initializes TEST_B with the constructor pointer argument call gives the following two errors in the VS 2019 compiler:
Error C2664 'A::B::B(C *)': cannot convert argument 1 from 'A::C *' to 'C *'
Error C2512 'A::B': no appropriate default constructor available
My Attempts
The first error line got me thinking that I may need to change my forward class declarations to include their respective parent classes too, as such:
class A;
class A::B;
class A::C;
However, that appears to break the reference to class C completely, and any references to it in the header above it's definition treat it as an undefined reference (Identifier "C" is undefined.). It's as if there were no forward declarations at all.
Adding A:: to each reference to class C in the rest of the header as such:
class A {
public:
class B {
public:
B(A::C* arg) {
ptr = arg;
}
A::C* ptr;
};
class C {
public:
...
};
};
didn't help either, instead the compiler tells me Class "A" has no member "C"..
However, one interesting thing that I did notice, was the fact that if I change the argument being passed to the constructor call for class B, to nullptr, that is:
A::B TEST_B = *new A::B(nullptr);
then the code gets compiled without problems. To me, that meant that this is most likely an issue with my forward class declarations, where the compiler sees that there are classes B and C declared, but it doesn't get to reading the actual content of the classes prior to attempting to reference them.
Is what I'm trying to accomplish here even possible with C++? Is there a way I should be doing this properly, that I'm not seeing?
Thank you in advance for reading my post, any help is appreciated!
The problem is that you've forward declared class C in global namespace instead of class scope A. This means that there are two different class named C one of which is declared to be in the global namespace ::C and the second one as an inner class A::C.
To solve this, just move the forward declaration of class C to inside class scope A as shown below:
header.h
class A {
public:
class C;// forward declaration moved here inside class scope A
class B {
public:
B(C* arg) {
ptr = arg;
}
C* ptr;
};
class C {
public:
};
};
Working demo
Also, be careful about other logical bugs like memory leak(if any) in your program.
class A {
public:
class C;
class B {
public:
B(C* arg) {
ptr = arg;
}
C* ptr;
};
class C {
public:
...
};
};

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.

invalid use of non-static data member

For a code like this:
class foo {
protected:
int a;
public:
class bar {
public:
int getA() {return a;} // ERROR
};
foo()
: a (p->param)
};
I get this error:
invalid use of non-static data member 'foo::a'
currently the variable a is initialized in the constructor of foo.
if I make it static, then it says:
error: 'int foo::a' is a static data member; it can only be initialized at its definition
However I want to pass a value to a in the constructor.
What is the solution then?
In C++, unlike (say) Java, an instance of a nested class doesn't intrinsically belong to any instance of the enclosing class. So bar::getA doesn't have any specific instance of foo whose a it can be returning. I'm guessing that what you want is something like:
class bar {
private:
foo * const owner;
public:
bar(foo & owner) : owner(&owner) { }
int getA() {return owner->a;}
};
But even for this you may have to make some changes, because in versions of C++ before C++11, unlike (again, say) Java, a nested class has no special access to its enclosing class, so it can't see the protected member a. This will depend on your compiler version. (Hat-tip to Ken Wayne VanderLinde for pointing out that C++11 has changed this.)
In C++, nested classes are not connected to any instance of the outer class. If you want bar to access non-static members of foo, then bar needs to have access to an instance of foo. Maybe something like:
class bar {
public:
int getA(foo & f ) {return foo.a;}
};
Or maybe
class bar {
private:
foo & f;
public:
bar(foo & g)
: f(g)
{
}
int getA() { return f.a; }
};
In any case, you need to explicitly make sure you have access to an instance of foo.
The nested class doesn't know about the outer class, and protected doesn't help. You'll have to pass some actual reference to objects of the nested class type. You could store a foo*, but perhaps a reference to the integer is enough:
class Outer
{
int n;
public:
class Inner
{
int & a;
public:
Inner(int & b) : a(b) { }
int & get() { return a; }
};
// ... for example:
Inner inn;
Outer() : inn(n) { }
};
Now you can instantiate inner classes like Inner i(n); and call i.get().
You try to access private member of one class from another. The fact that bar-class is declared within foo-class means that bar in visible only inside foo class, but that is still other class.
And what is p->param?
Actually, it isn't clear what do you want to do
Your Question is not clear but there is use case when you will get this issue .
Invalid use of non-static data member.
When you are using "non-static data member in another class try to not use with scope resolution operator
Example::className::memberData = assignivalue ;
instead of above try to use object of className class;
Example:: m_pClassName->memberData=assignValue;*

Question about C++ inner class

HI,
In C++ inner class,
class A {
public:
void f1();
private:
void f2();
class B {
private void f3();
};
}
Does an inner class (B) has a pointer to its parent class (A)? (like it does in Java).
And can B calls its parent class public/private method (like it does in Java).
Thank you.
No -- in C++, nesting classes only affects names and visibility, not the semantics of the class itself. As far as generated code goes, the nested class is no different from one that isn't nested.
All that's changed is the visibility and the name (e.g. if it's in a private: section of the outer class, it's not visible to the outside world, and if it's in a public: section, it's visible, but (of course) to name it you use outer_class::inner_class. It's still a completely separate class though -- just for example, you can create an instance of the inner class without creating any instance of the outer class.
Edit: Sorry, I missed part of your question. In C++ 0x, the inner class does have access to the the private parts of the outer class -- in essence, it's as if the outer class has declared the inner class as its friend, so private names are visible, but you still need to pass it something like a reference to an object of the outer class before it can invoke any non-static member functions of the outer class.
Although this isn't supposed to be the case yet, I believe most compilers implement this particular part already.
No, Class B does not have a pointer to Class A, unless you explicitly add it.
Does it have a pointer to the parent: No.
Does it have access to the parents private members: Sort of
I think the if it has access is not well defined in the standard I could be wrong.
But you can access it in g++
#include <iostream>
class X
{
class Y
{
public:
Y(X* p)
:parent(p)
{}
void TryY()
{
// Access a private member of X
++(parent->value);
}
private:
X* parent;
};
public:
X()
:y(this)
{
value = 4;
}
void TryY()
{
y.TryY();
std::cout << value << std::endl;
}
private:
Y y;
int value;
};
int main()
{
X x;
x.TryY();
}

C++ overload resolution [duplicate]

This question already has answers here:
Function with same name but different signature in derived class not found
(2 answers)
Closed 8 years ago.
Given the following example, why do I have to explicitly use the statement b->A::DoSomething() rather than just b->DoSomething()?
Shouldn't the compiler's overload resolution figure out which method I'm talking about?
I'm using Microsoft VS 2005. (Note: using virtual doesn't help in this case.)
class A
{
public:
int DoSomething() {return 0;};
};
class B : public A
{
public:
int DoSomething(int x) {return 1;};
};
int main()
{
B* b = new B();
b->A::DoSomething(); //Why this?
//b->DoSomething(); //Why not this? (Gives compiler error.)
delete b;
return 0;
}
The two “overloads” aren't in the same scope. By default, the compiler only considers the smallest possible name scope until it finds a name match. Argument matching is done afterwards. In your case this means that the compiler sees B::DoSomething. It then tries to match the argument list, which fails.
One solution would be to pull down the overload from A into B's scope:
class B : public A {
public:
using A::DoSomething;
// …
}
Overload resolution is one of the ugliest parts of C++
Basically the compiler finds a name match "DoSomething(int)" in the scope of B, sees the parameters don't match, and stops with an error.
It can be overcome by using the A::DoSomething in class B
class A
{
public:
int DoSomething() {return 0;}
};
class B : public A
{
public:
using A::DoSomething;
int DoSomething(int x) {return 1;}
};
int main(int argc, char** argv)
{
B* b = new B();
// b->A::DoSomething(); // still works, but...
b->DoSomething(); // works now too
delete b;
return 0;
}
No, this behaviour is present to ensure that you don't get caught out inheriting from distant base classes by mistake.
To get around it, you need to tell the compiler which method you want to call by placing a using A::DoSomething in the B class.
See this article for a quick and easy overview of this behaviour.
The presence of a method in a derived class hides all methods with the same name (regardless of parameters) in base classes. This is done to avoid problems like this:
class A {} ;
class B :public A
{
void DoSomething(long) {...}
}
B b;
b.DoSomething(1); // calls B::DoSomething((long)1));
than later someone changes class A:
class A
{
void DoSomething(int ) {...}
}
now suddenly:
B b;
b.DoSomething(1); // calls A::DoSomething(1);
In other words, if it didn't work like this, a unrelated change in a class you don't control (A), could silently affect how your code works.
This has something to do with the way name resolution works. Basically, we first find the scope from which the name comes, and then we collect all overloads for that name in that scope. However, the scope in your case is class B, and in class B, B::DoSomething hides A::DOSomething:
3.3.7 Name hiding [basic.scope.hiding]
...[snip]...
3 In a member function definition, the declaration of a local name hides
the declaration of a member of the class with the same name; see
basic.scope.class. The declaration of a member in a derived class
(class.derived) hides the declaration of a member of a base class of
the same name; see class.member.lookup.
Because of name hiding, A::DoSomething is not even considered for overload resolution
When you define a function in a derived class then it hides all the functions with that name in the base class. If the base class function is virtual and has a compatible signature then the derived class function also overrides the base class function. However, that doesn't affect the visibility.
You can make the base class function visible with a using declaration:
class B : public A
{
public:
int DoSomething(int x) {return 1;};
using A::DoSomething;
};
That's not overloading! That's HIDING!
When searching up the inheritance tree for the function to use, C++ uses the name without arguments, once it has found any definition it stops, then examines the arguments. In the example given, it stops in class B. In order to be able to do what you are after, class B should be defined like this:
class B : public A
{
public:
using A::DoSomething;
int DoSomething(int x) {return 1;};
};
The function is hidden by the function with the same name in the subclass (but with a different signature). You can unhide it by using the using statement, as in using A::DoSomething();