If I have the following nested classes:
class foo {
public:
class bar {
public:
int barMethod() const;
protected:
int barVar;
};
protected:
int fooVar;
};
and then in a .cpp, can I implement barMethod() this way?
int foo::bar::barMethod() const {
return this->fooVar + this->barVar;
}
What I mean is:
does this keyword in a nested class refer to all classes that are upstream in hierarchy?
does this keyword in a nested class refer to all classes that are upstream in hierarchy?
No, "current" class only. Class nesting is mostly a lexical thing. Unlike in, say, Java, where an inner class can be associated with an instance of an enclosing outer class, foo::bar is pretty much like any other class that isn't nested.
If you want to associate an instance of bar with an instance of foo, you need to capture a reference or a pointer to foo in bar.
Related
I have a global class TRK that has many members and methods. I wanted to organize these by sorting them into different named categories, e.g. Fitting, such that the namespace of the main class isn't overcrowded. In a perfect world, I would want this example to work:
class TRK
{
public:
// constructors
TRK(...);
...
TRK();
~TRK();
// nested classes
class Fitting;
// and many other methods...
private:
...
};
class TRK::Fitting
{
public:
// constructors/destructor
TRK& trk;
Fitting();
~Fitting();
// and many other methods...
private:
...
};
The key thing here that I need is to be able to:
Instance some TRK object using one of the TRK class' constructors, and I need the TRK constructors to be able to also automatically instantiate accompanying nested classes e.g. Fitting, for that instance of TRK. I then need to be able to instantiate/give values to members of these nested classes, within the TRK constructors. For example, if Fitting has some member x, I need to be able to initialize the value for x for that instance of TRK within the TRK constructor, given the arguments to the constructor. What I'm unclear on is how exactly to go about this; how and where can I instantiate these nested classes?
Access members of the nested classes from TRK instances and methods, and vice versa. I already can do the latter by passing TRK by reference to the nest classes, as shown, but I'm not sure how to do the former.
For example, I have methods of Fitting that need to use members of whatever TRK instance that that instance of Fitting was created within. Similarly, I have methods of Fitting that methods of TRK need to be able to call.
Should I even be using nested classes for this? I tried using namespaces and inheritance but I couldn't get things to work the way that I wanted. My core issue here is attempting
Constructing instances of nested classes
If you want the constructor of TRK to in turn cause the construction of a TRK::Fitting variable, the definition of TRK::Fitting must be completely known to it, a forward declaration is not enough. However, once you do that, you can intialize member variables of the nested class type just like you would always do. Here is an example:
class TRK {
class Fitting {
int x;
public:
Fitting(int x): x(x) {}
};
Fitting fitting;
public:
TRK(int y): fitting(y) {}
};
Having nested classes access the parent class
A nested class is just a regular class, only its name is nested. It does not automatically know where the non-static member variables of the parent are. A simple solution is to provide the nested class with a reference to the instance of the parent class, like so:
class TRK {
class Fitting {
TRK &parent;
int x;
public:
Fitting(TRK &parent, int x): parent(parent), x(x) {}
void foo() {
// Use something from the parent class
parent.bar();
}
};
Fitting fitting;
public:
TRK(int y): fitting(*this, y) {}
void bar() {}
};
Another option is to not store a reference to the parent in the child class, but rather to explicitly pass a reference to the parent to every member function of the child class:
class TRK {
class Fitting {
void foo(TRK &parent) {
// Use something from the parent class
parent.bar();
}
};
Fitting fitting;
public:
TRK(int y): fitting(y) {}
void bar() {}
void quux() {
fitting.bar(*this);
}
};
Calling a member function of the child class from the parent class is easy, as shown in TRK::quux().
If you want to use inheritance and have the base class be able to call functions in the derived class, then the curiously recurring template pattern can be used, like so:
template <typename Derived>
class TRK {
...
void bar() {}
void quux() {
// We need to static_cast<> ourself to get an object of type Derived
static_cast<Derived>(*this)::foo();
}
};
class Derived: TRK<Derived> {
...
void foo() {
// We can directly call any base class member functions here
bar();
}
}
I have
class outer: public base
{
public:
class inner
{
foo();
}
}
How do i initialize these nested class?
Can I call foo() from the outer class?
Can you please tell me what is the thumb rule I should know while nesting class and accessing the members?
Thank you
I guess you're coming from java.
A c++ nested struct/class is like a java static nested type. It has no instance-relation with the containing type.
In fact you should be able to move the inner class to the containing namespace with no other changes than the potential need to mark the former inner class as a friend of the outer class.
See for demonstration http://ideone.com/ddjGX
How do i initialize these nested class?
You don't. You can only initialize members (class instances)
Can I call foo() from the outer class?
Not unless you are a friend or the method (foo()) is public
Can you please tell me what is the thumb rule I should know while nesting class and accessing the members?
I'd choose a nested type only if
the type is an implementation detail or depends on the outer class
the convenience of sharing static members (enums, typedefs, template arguments, static methods and fields) from the outer class: the inner class is implicitly a friend of the outer class.
I illustrated these 'rules of thumb' below. Note how the nested type has transparent access to private members of the outer class.
struct base {};
class outer: public base
{
private:
enum { some=42, special=67, implementation=999, details=-13 };
public:
struct inner
{
protected:
void foo() { int can_usethis = special + implementation + details; }
};
outer() : _inner() { }
void call_inner(inner& i) const
{
//i.foo(); // fails (protected)
}
void call_inner() const
{
//_inner.foo(); // fails (protected)
}
private:
inner _inner;
};
int main()
{
outer o;
outer::inner i;
// i.foo(); // fails: protected
o.call_inner(i);
}
You can instance inner object using scope operator :: (outer::inner()) . If you want to acceess foo() from outer class you maybe want to define outer like friend class of inner.
So my Idea is simple - to have a class that can have its own public methosds and a nested class that would forvard only some of that public methods (pseudocode):
class API
{
public:
go();
stop();
friend class B
{
public:
void public_request()
{
request();
}
void public_go()
{
go()
}
};
private:
void request(){}
};
Is it possible to implement such nested class in C++ and how?
It is possible to create a Local class in C++. Local class is a class defined inside an function.
But such an class has several restrictions. Read about it here in detail.
You cannot create Nested classes in C++ like Java though. Nested class is a class within the scope of another class.
The name of a nested class is local to its enclosing class(It is not visible outside the scope of the enclosing class). Unless you use explicit pointers or references, declarations in a nested class can only use visible constructs, including type names, static members, and enumerators from the enclosing class
Two important points to note with Nested classes are:
Member functions of a nested class follow regular access rules and have no special access privileges to members of their enclosing classes.
Member functions of the enclosing class have no special access to members of a nested class.
So You will need to use composition or explicitly pass a pointer or reference of object of outer class to the nested class
Yes, but you have to provide an instance of the outer class when you create the inner one... the two types are [mostly] independant, so B is not associated with any specific instance of API.
More pseudo-code
struct API {
void go();
struct B {
B(API& api) : api(api) { }
void go() { api.go(); }
};
};
API a;
B b(a);
b.go();
Alternatively, you can pass an instance of API to B's function [B::go(API&)]
struct API {
void go();
struct B {
void go(API& api) { api.go(); }
};
};
API a1, a2;
B b;
b.go(a1);
b.go(a2);
Further, API does not contain an instance of B unless you explicitely add an instance.
struct API {
struct B { };
B b;
};
Also, note that B does not need to be granted friendship by API. As an inner class, B can already access APIs private/protected members. The converse is not true, however... API can not access Bs private/protected members unless B grants it permission.
Not directly, at least not in the same way as in Java. Your nested class has to contain a pointer or a reference to the "outer" class.
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.
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();
}