令我感到惊讶的是,在下面的示例中,声明Middle的基类private使该名称在后续派生中不可用作为类型.
class Base {
public:
Base(Base const& b) : i(b.i) {}
int i;
};
class Middle : private Base { //<<<<<<<<<<<
public:
Middle(Base const* p) : Base(*p) {}
};
class Upper : public Middle {
public:
Upper(Base const* p) : Middle(p) {} //<<<<<<<<<<<
};
Run Code Online (Sandbox Code Playgroud)
用g ++编译(Debian 6.3.0-18 + deb9u1)6.3.0 20170516 ......
g++ -std=c++11 privateBase.cpp
Run Code Online (Sandbox Code Playgroud)
我得到以下诊断:
privateBase.cpp:15:9: error: ‘class Base Base::Base’ is inaccessible within this context
Upper(Base const* p) : Middle(p) {}
^~~~
privateBase.cpp:1:12: note: declared here
class Base {
^ …Run Code Online (Sandbox Code Playgroud) 在以下情况中,inject-class-name被视为类模板本身的模板名称:
- 接下来是<
- 它用作与模板模板参数对应的模板参数
- 它是友元类模板声明的详细类说明符中的最终标识符.
所以我试图检查所有3个案例(另外在基础模糊的背景下,虽然我认为这不应该在这里).
第一种情况似乎很简单.
问题是 - 为什么没有注释出实例?他们不在GCC和Clang上,所以我不认为这是一个实施问题
template <template <class> class> struct A;
template <class T> struct Base {};
template <class T> struct Derived: Base<int>, Base<char>
{
// #1
typename Derived::Base<double> d;
// #2
// using a = A<Base>;
using a = A<Derived::template Base>;
// #3
template<class U1>
friend struct Base;
// template<class U>
// friend struct Derived::template Base;
};
Run Code Online (Sandbox Code Playgroud)
以上规则仅适用于模板本身,而不适用于基础吗?如果是这样,基数的规则是什么,特别是对于最后两个案例?
考虑这个代码:
template <typename T>
class Singleton
{
};
class Logger : public Singleton<Logger> {
friend class Singleton;
};
Run Code Online (Sandbox Code Playgroud)
它在 gcc 和 clang 中编译,但它有效吗?[temp.local].1 说:
当它与模板参数列表一起使用时,作为模板模板参数的模板参数,或作为朋友类模板声明的详细类型说明符中的最终标识符,它是一个模板名称指的是类模板本身。
粗体部分似乎适用,并且朋友声明似乎需要类型名称而不是模板名称(参见 [class.friend])。
编译器错了还是我误读了标准?
c++ friend-class language-lawyer class-template injected-class-name
考虑下面的示例:
template <typename T>
class SomeClass {
// rest of the definition ...
SomeClass<T>& function1() {
// ...
return *this;
}
SomeClass& function2() {
// ...
return *this;
}
}
Run Code Online (Sandbox Code Playgroud)
上面两个函数的返回值之间有区别吗?如果不是,应该选择哪一个?
根据https://en.cppreference.com/w/cpp/language/injected-class-name
在类作用域中,当前类的名称被视为公共成员名称;这称为注入类名。名称的声明点紧跟在类定义的左大括号之后。
int X;
struct X {
void f() {
X* p; // OK. X refers to the injected-class-name
::X* q; // Error: name lookup finds a variable name, which hides the struct name
}
};
Run Code Online (Sandbox Code Playgroud)
那么代码中到底发生了什么?是X* p变成了X::X* p?
我读的怪C++的功能,称为大约一个注入的类名 在这里.
我试过按照简单的程序
#include <iostream>
class test
{
int s{3};
public:
int get_s()
{ return s; }
};
int main() {
class test::test s; // struct test::test s; also allowed. Why???
std::cout<<s.get_s();
}
Run Code Online (Sandbox Code Playgroud)
如果我在main()程序的第一行用struct替换class关键字仍然编译并运行正常.在这里查看现场演示.为什么?我不应该得到编译错误吗?为什么编译好?
我正在编写链表的实现
在下面的代码中,Node<T> * next;我Node * next;
认为两者的作用与指向 Node 类的对象相同,或者它们之间存在差异。
template<typename T>
class Node{
T data;
Node<T>* next;
Node * next;
Node()
{
next = nullptr;
}
Node(T val)
{
this->data = val;
next = nullptr;
}
};
Run Code Online (Sandbox Code Playgroud)