2

In the following complete program:

#include <vector>

class Derived : private std::vector<int> {
public:
  void f();
};

void Derived::f() {
  Derived d;

  d.std::vector<int>::push_back(0);
}

int main() {
  Derived d;

  d.f();
}

the line

d.std::vector<int>::push_back(0);

can be replaced by

d.vector<int>::push_back(0);

and the compilation would complete w/o warning both in gcc 7 and clang 6. I don't understand why the std:: part of the scope resolution is optional, since there's no using namespace std declaration.

davide
  • 2,082
  • 3
  • 21
  • 30
  • 3
    I think that `vector` is the injected class name, which indeed does not come with any namespace prefix. – Quentin Jun 26 '18 at 14:54
  • 2
    Protip: don't inherit from STL, your destructor won't run T.T – Jonathan Mee Jun 26 '18 at 15:01
  • 1
    @JonathanMee Huh? – Praetorian Jun 26 '18 at 15:05
  • @Praetorian `std::vector`'s destructor is not virtual. – Jonathan Mee Jun 26 '18 at 15:06
  • 1
    @JonathanMee I'm aware, but none of that is applicable to this example, and your blanket statement is not accurate in general anyway. – Praetorian Jun 26 '18 at 15:07
  • 1
    @JonathanMee -- the destructor won't run (in fact, the behavior is undefined) **only if** an object of type `Derived` is deleted through a pointer to its base. – Pete Becker Jun 26 '18 at 15:12
  • It's using private inheritance, so this pointer to base, non-virtual destructor call, is not going to happen anyway. – ROX Jun 27 '18 at 12:18
  • @ROX wrong. access specifiers on subojects or data members do not prevent their dtors from being called. – Red.Wave Jun 28 '18 at 17:38
  • @Red.Wave The private inheritance stops objects of derived being referenced via pointers or references to vector, which in turn stops the slicing which is being commented on. – ROX Jun 29 '18 at 10:00
  • @ROX We were discussing dtor. Right? – Red.Wave Jun 29 '18 at 10:06
  • @Red.Wave yes, specifically that derived's dtor "won't run" because "vector's destructor is not virtual" aka slicing (which won't happen here since derived cannot be referred to as a reference/pointer to vector anyway) – ROX Jun 29 '18 at 10:24
  • @ROX Wrong. The dtor is called by the dtor of derived type which can access the base dtor, simply becuase base dtor ix not declared private. Are you sure you have a good command of inheritance in c++? – Red.Wave Jun 29 '18 at 10:31
  • @Red.Wave WOW! rather rude. I understand fine. Other than "wrong" (and the comments on my understanding), what you've said is correct - it's just not the point being made by me or in other's comments. Yes the vector's dtor gets called by derived's dtor as you said. Nobody here- including me has - said otherwise. What was claimed was that DERIVED's dtor wouldn't get called (which would be an example of slicing). Pete Becker 's comment already explains the conditions needed for the slicing. I've added that that condition doesn't occur here. – ROX Jun 29 '18 at 10:47
  • @ROX I do not see any reason for that. we are not casting a temporary to a reference. No copying to base is involved. And slicing is irrelevant. And I sm not rude. I strongly beleive you need more study and practice. – Red.Wave Jun 29 '18 at 10:54

1 Answers1

1

As others already mentioned:

Do not inherit from STL!

See this and this and read Effective c++ book.

Apart from the derivation from STL, it could be an everyday problem. I think you are searching for how qualified name lookup works.

Consider the following code

#include <iostream>
#include <string>

namespace myNamespace {
    namespace nested {
        class base {
        protected:
            std::string print() { return "Fantastic"; };
            static const int four= 4;
        };
    }
}

class derived : private myNamespace::nested::base
{
public:
    // no need to extra qualify base class methods, since derived access the scope of the base class 
    std::string doStuff() { return print() + std::to_string(four); };
};

int main()
{
    derived d;
    std::cout << d.doStuff();
}

It has the same structure, deriving from something that is a part of a namespace. As you noticed, in the derived there is no need to extra qualify the print method. However, the following is completely legal call in the doStuff method:

print();
base::print();
myNamespace::nested::base::print();

Note that simply nested::base::print(); is not legal - myNamespace should be used.

Ps. I compiled with MSVC 143, and always produced this output:

Fantastic4

zerocukor287
  • 555
  • 2
  • 8
  • 23