C++ 11标准§12.3.2/ 1(强调我的):
甲成员函数具有以下形式的名称没有参数的类X的
conversion-function-id:
operator convert-type-id
conversion-type-id:
type-specifier-seq conversion-declarator
转换声明者:
ptr-operator转换声明器
指定从X到convert-type-id指定的类型的转换.这些功能称为转换功能.不能指定返回类型.如果转换函数是成员函数,则转换函数的类型(8.3.5)是"不返回convert-type-id的参数的函数".
转换函数是否始终是成员函数,或者有些情况不是这样?
一个类的完整类上下文是
(6.1)函数体,
(6.2)默认参数,
(6.3)noexcept-specifier([except.spec]),
(6.4)合同条件或
(6.5)默认成员初始化器在类的成员规范内。[?注意:如果嵌套类是在封闭类的成员规范内定义的,则嵌套类的完整类上下文也是任何封闭类的完整类上下文。-?尾注?]
上面突出显示的文本似乎为以下代码段提供了支持:
#include<iostream>
struct A{
int i = j + 1;
int j = 1;
};
int main(){
A a;
std::cout << a.i << '\n';
std::cout << a.j << '\n';
}
Run Code Online (Sandbox Code Playgroud)
,并且我希望它能打印出来
2
1
Run Code Online (Sandbox Code Playgroud)
无论GCC和铛打印
1
1
Run Code Online (Sandbox Code Playgroud)
但另外clang发出以下警告:
prog.cc:3:13: warning: field 'j' is uninitialized when used here [-Wuninitialized]
int i = j + 1;
^
prog.cc:8:7: note: in implicit default constructor for 'A' first required here
A …Run Code Online (Sandbox Code Playgroud) 下面的段落摘自Stroustup的书"The C++ Programming Language"(第三版)第420页:
因为指向虚拟成员的指针(在此示例中为s)是一种偏移量,所以它不依赖于对象在内存中的位置.因此,只要在两者中使用相同的对象布局,就可以安全地在不同的地址空间之间传递指向虚拟成员的指针.与普通函数的指针一样,指向非虚拟成员函数的指针不能在地址空间之间交换.
我在争论本段最后一句话.下面,您将找到一个代码片段,其中指向非虚拟成员函数的指针,foo()以及foo1()在一个基础对象a和派生对象之间交换b,没有问题.
不能做的是重载,基类中的任何函数,foo()或者foo1()在派生类中,在这种情况下,编译器将发出错误,如下所示.
#include <iostream>
class A
{
int i;
public:
A() : i(1) {}
void foo() { std::cout << i << '\n'; }
void foo1() { std::cout << 2 * i << '\n'; }
};
class B: public A
{
int j;
public:
B() : A(), j(2) {}
// void foo() { std::cout << j << '\n'; }
};
int main() …Run Code Online (Sandbox Code Playgroud) 根据[dcl.fct]/2,下面的代码段是合法的.GCC和clang编译并执行代码,
#include <iostream>
int i = -1;
auto f()->auto&& { return i; }
int main(){
f() = 2;
std::cout << i << '\n';
}
Run Code Online (Sandbox Code Playgroud)
印花
2
Run Code Online (Sandbox Code Playgroud)
但是在C++中允许这个的目的是什么?
在上面的示例中,只需将trailing-return-type替换为,就可以获得相同的结果int&.换句话说,我正在寻找一个示例,其中包含占位符类型的trailing-return-type将是有意义的.
这是第一次,在使用Windows API的多年经验中,我遇到了一种情况,我需要做一些事情,我不能用Windows当前的编程接口.
根据我的研究,字体"Arial Black"使用该文件,arialblk.ttf并且字体"Arial Black Italic"没有文件,也没有字体"Arial Black Bold",至少在我的Windows 7计算机中.
我插入一个程序下方,用单独的字体"Arial Black"显示几行文字,然后用斜体和粗体显示.令我惊讶的是,斜体文本正常呈现,粗体文本呈现为"Arial Black".然后我意识到MS Word也会发生同样的事情.我还插入了Word文档的屏幕截图,由下面的代码输出叠加.这里发生了什么事 ?我是否必须猜测,在每种情况下使用哪个字体文件?显然Windows API没有给我答案的可能性.为何如此神秘?
#include <Windows.h>
LRESULT CALLBACK WndProc(HWND, UINT, UINT, LONG);
int APIENTRY WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR pszCmdLine, int nCmdShow)
{
WNDCLASSEX wndclassx;
wndclassx.cbSize = sizeof(WNDCLASSEX);
wndclassx.style = CS_HREDRAW | CS_VREDRAW;
wndclassx.lpfnWndProc = WndProc;
wndclassx.cbClsExtra = 0;
wndclassx.cbWndExtra = 0;
wndclassx.hInstance = hInstance;
wndclassx.hIcon = nullptr;
wndclassx.hCursor = LoadCursor(NULL, IDC_ARROW);
wndclassx.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wndclassx.lpszMenuName = nullptr;
wndclassx.lpszClassName = L"WndProc";
wndclassx.hIconSm = nullptr; …Run Code Online (Sandbox Code Playgroud) 下面的代码生成一个悬空引用,可以在编译器发出的警告中看到,并且在函数返回之前调用A函数中对象的析构g()函数.还可以验证在main()"使用堆栈"之后,返回的引用具有垃圾,至少在调试版本中是这样.但我无法在发布版本中重现相同的行为.这是为什么?编译器在这里做了什么样的优化,给人的印象是引用r是OK?
#include <iostream>
struct A{
A(int i) : i(i) { std::cout << "Ctor\n"; }
A(const A& a) { i = a.i; std::cout << "Copy ctor\n"; }
~A() { std::cout << "Dtor\n"; }
int i;
};
A& g(int i) { A x(i); return x; }
int main()
{
const A& r = g(1);
std::cout << "Using the stack\n";
std::cout << r.i << '\n'; // r.i has garbage in debug, but not in a …Run Code Online (Sandbox Code Playgroud) 在Stroustrup的书(第4版 - 第一次打印)的第668页中,您将找到以下模板类示例?
template<typename C>
class String{
public:
String();
...
private:
int sz;
C* ptr;
};
Run Code Online (Sandbox Code Playgroud)
在第679页中,作者写道:
模板类的成员本身是由其模板类的参数参数化的模板.当这样的成员在其类之外定义时,它必须明确声明为模板.例如:
Run Code Online (Sandbox Code Playgroud)template<typename C> String<C>::String() :sz(0), ptr(ch) { ch[0] = {}; }
这个例子中有一个明显的错误.变量ch 在上面没有任何意义.但这与我的问题无关.我想知道的是为什么没有参数就无法定义上面的构造函数C,如下所示?
template<typename C>
String::String()
: sz(0), ptr(nullptr)
{
}
Run Code Online (Sandbox Code Playgroud) [basic.lookup.unqual]/3中的第一个例子:
int h;
void g();
namespace N {
struct A {};
template <class T> int f(T);
template <class T> int g(T);
template <class T> int h(T);
}
int x = f<N::A>(N::A()); // OK: lookup of f finds nothing, f treated as template name
int y = g<N::A>(N::A()); // OK: lookup of g finds a function, g treated as template name
int z = h<N::A>(N::A()); // error: h< does not begin a template-id
Run Code Online (Sandbox Code Playgroud)
上面的注释似乎表明编译器应该对名称g和h上面的查找进行不同的处理,就好像模板ID不会被考虑用于名称一样 …
一个完整的类的上下文是一个
(6.1)函数体,(6.2)默认参数,(6.3) noexcept-specifier([except.spec]),(6.4)合同条件,或(6.5)默认成员初始化程序
在类的成员规范内.[注意:如果嵌套类在封闭类的成员规范中定义,则嵌套类的完整类上下文也是任何封闭类的完整类上下文. - 结束说明]
该段落在草案中引入了拉动请求#2231.
据我所知,根据上面的注释,下面的代码应该编译.但事实并非如此.我假设GCC编译器仍然不是最新的草案.我是否正确,或者我对此笔记的理解是否正确?
struct A {
int i = 1;
struct B {
int j = 2;
int f() {
return i + j;
}
};
};
Run Code Online (Sandbox Code Playgroud)
哪个失败了:
source>: In member function 'int A::B::f()':
<source>:6:20: error: invalid use of non-static data member 'A::i'
6 | return i + j;
| ^
<source>:2:9: note: declared here
2 | int i = 1;
| …Run Code Online (Sandbox Code Playgroud)