Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using private nested type as parameter

Tags:

c++

I'm getting this strange problem which I don't know why happens. The first and second of the following code snippets compile, while the third does not:

Compiles:

class Foo {
public:
    Foo() { Bar(); }

private:
    class Bar {};
};

Compiles:

class Foo {
    class Bar {};  // Or only forward declare here and define later

public:
    Foo(Bar) {}
}

Does not compile:

class Foo {
public:
    Foo(Bar) {}

private:
    class Bar {};
};

What makes the third fail to compile while the first can?

like image 267
Zizheng Tai Avatar asked May 06 '16 22:05

Zizheng Tai


People also ask

How do I access private nested classes?

Accessing the Private Members Write an inner class in it, return the private members from a method within the inner class, say, getValue(), and finally from another class (from which you want to access the private members) call the getValue() method of the inner class.

Can nested classes be private?

Static nested classes do not have access to other members of the enclosing class. As a member of the OuterClass , a nested class can be declared private , public , protected , or package private.

Can nested classes access private members C#?

A nested type has access to all of the members that are accessible to its containing type. It can access private and protected members of the containing type, including any inherited protected members.

Can inner class access private variables?

It can access any private instance variable of the outer class. Like any other instance variable, we can have access modifier private, protected, public, and default modifier. Like class, an interface can also be nested and can have access specifiers.


2 Answers

Normally, in C++, you can only reference declarations that were previously made in the translation unit. However, within a class definition, the definition of member functions are allowed to reference declarations which are made later in the class. Basically, the compiler restructures your in-class definitions so that they work as though they were written just after the class.

But this is only true of the function definitions. The declaration of the function (including parameter types) isn't allowed to do this. They can only reference declarations that have already been made in file order.

So you can do this:

class Test
{
    public:
      void Func(int x) {Inner foo;}

    private:
      class Inner {};
};

But not this:

class Test
{
    public:
      void Func(Inner x) {}

    private:
      class Inner {};
};
like image 200
Nicol Bolas Avatar answered Oct 12 '22 21:10

Nicol Bolas


First example does not expose anything about private Bar to the outside, while third does.

Third example is pretty much saying, that there exist some class Foo, which has constructor with single argument of type Bar. But Bar is unknown to the outside. Imagine calling such constructor.

Foo f{Foo::Bar{}};

Will result probably in something like Foo::Bar is inaccessible.

like image 23
Zereges Avatar answered Oct 12 '22 21:10

Zereges