各位好!百度了一下也不是太清楚:
#include <iostream>
#include <memory>
using namespace std;
class A {
public:
typedef shared_ptr<A> Ptr;
int a = 10;
void test(){
std::cout << a << std::endl;
}
};
int main()
{
A foo;
cout << foo.a << endl;
A::Ptr bar;
//cout << A::a << endl;
//foo.Ptr c;
}
假如这里Ptr
被当成类型,它算不算一个实例变量呢?注释的两行都是不可以的。我看很多都是这样写的,那我为什么不在要用Ptr
的时候在类外面需要的时候定义?typedef shared_ptr<A> Ptr
再用也没错啊。
1
429839446 2019-04-11 20:14:55 +08:00
这好像是依赖类型, 典型的像 stl 容器里面的各种类型, ::value_type, ::iterator, ::const_interator 之类, 加了类的命名空间可以防止冲突. 在泛型或者模板元的时候, 可以直接获取这些类型做一些操作. 另外类静态方法和静态变量可以. 访问也可以::访问, 为了显示指出这一点,我一般用后者访问
|
2
across 2019-04-11 20:17:51 +08:00 via iPhone
typedef 相当于增加个别名,Ptr 和 shared_ptr<A>一个意思。
这么想,反正 . 前面的就是个实例。 |
3
wevsty 2019-04-11 20:26:25 +08:00 1
::前面的是命名空间的名字,后面可以是类型,也可以是函数。
.前面是一个具体类型的实例,后面是这个实例对应的成员,成员函数。 |
4
zealot0630 2019-04-11 20:32:49 +08:00
这是 C++以及众多语言的设计缺陷之一,滥用 static 概念。
未防止歧义,我用 /代表 . 或者 :: 1. foo/Ptr 和 bar/Ptr 是同一个东西么?是,所以本质上 Ptr 是属于类的。 2. foo/a 和 bar/a 是同一个东西么?不是,所以本质上 a 是属于对象的。 访问类内东西使用 :: 访问对象内东西使用 . |
5
GjriFeu 2019-04-11 20:49:24 +08:00
@zealot0630 那如果我定义的是 static int a; foo/a 和 bar/a 是同一个东西么?是
|
6
zealot0630 2019-04-11 20:55:40 +08:00 via Android
是啊 所以要用 类::a 访问
|
7
Yggdroot 2019-04-11 21:15:32 +08:00
首先,你要搞清楚,Ptr 是 typedef 的一个类型,不是实例变量,比如可以认为 Ptr 是个 int,这样就不会糊涂了。注释里的 foo.Ptr 这种写法,就像写 foo.int 一样,明显是不对且无意义的。
> 那我为什么不在要用 Ptr 的时候在类外面需要的时候定义? typedef shared_ptr<A> Ptr 再用也没错啊 你这样也没错,定义在类里面,只是作用域在类里面,对外面不可见,如果外面想访问,必须指定作用域,也就是 A::Ptr。 A::a 不可以这样,是因为 a 不是静态变量,静态变量是属于类的,故可以写成 A::a。非静态变量是属于每个实例的,不可以写成 A::a。 |
8
Yggdroot 2019-04-11 21:19:37 +08:00
@zealot0630 > 1. foo/Ptr 和 bar/Ptr 是同一个东西么?是,所以本质上 Ptr 是属于类的。
他们是同一个东西,因为他们都是错误写法。因为 Ptr 是个类型,而不是变量,不存在变量 /类型这种写法。 |
9
eret9616 2019-04-11 21:24:46 +08:00
typedef 在编译阶段将 shared_ptr 加上 Ptr 这个别名
进入 main 函数开始执行, A::Ptr bar; 这句话是声明变量, 数据机构是类 A 中 Ptr , 在栈上分配,这个变量名是 bar A::a 是声明变量 所以不能 cout foo 是实例化的对象... 不要和声明搞混啊 |
10
eret9616 2019-04-11 21:28:42 +08:00
另外看不懂楼上们在说什么...
|
11
missdeer 2019-04-11 22:20:48 +08:00 via Android
7 楼正解
|
12
shoujiaxin 2019-04-11 22:38:54 +08:00 via iPhone
@zealot0630 请教一下,为什么 . 和 :: 是设计缺陷呢?以及它们和 static 概念有什么关系?没太搞明白
|
13
GeruzoniAnsasu 2019-04-12 00:20:50 +08:00 2
hhhhhh 建议暂时先记住用法,这块能展开的东西多了去了
::这个符号跟 C++最邪恶晦涩的部分( templates )紧密相关,但简单来说,他只有一个含义,就是“属于 namespace ” A::a 这个语法,在 C++里,是 ambiguous 的,唯一能确定的是,a 在 A namespace 中(如果把 class 也看做是 namespace 的话),所以先不要先入为主认为 A::a 一定是表示变量或者类型,实际上 A 也好 a 也好,它们可以是变量,可以是类型,甚至还可以是一个 incomplete type (在类型推导中),一个最令人颤抖的例子是 STO 上关于 C++语言是否是 context-free 的讨论: https://stackoverflow.com/questions/14589346/is-c-context-free-or-context-sensitive 由于 C++的 templates 是 Turing Complete 的,所以,推导 A::a 的 a 到底是什么东西,的这个过程,是 Turing Complete 的,理论上你可以写出一个“推测出 a 是什么东西的时候处理完一次 HTTP 请求”这样的程序 与之相比,A.a,必定代表 访问 对象 A 的成员 a,a 一定被绑定到实例 A,这个 syntax 是不存在歧义性的 然后至于为什么要有::这种东西 这么说,当你不需要用 templates 的时候,它仅仅表示一个名字所属的限定,真的没什么用,你甚至可以手动 A_B_c 这样子从命名上划分 namespace 但用到 templates 的时候,模板有一个决定性的特性是 A<特化 1>::v 与 A<特化 2>::v 可以不同,但不同的 v 都可以用同一个 dependent type 去使用,这个时候 A<T>::v 的 v 是什么取决于 T,而 T 是可随着模板实例化位置的上下文不同,会自动改变的!这个时候可以说::的作用是使一个 type 能够依赖于另一个 type,而这也编译期多态的关键 展开太多估计也看不懂,而且我表达得也很可能不准确。 四点: c++里 value 和 type 永远是俩种东西,不存在 python 中“ class 是 type object ”这么混沌的语义 c++里::这个运算符仅仅表示 namespace 所属,左右两边到底是 type 还是 value 都有可能 就你的例子来说 typedef 在外面当然可以,但定义在里面的 dependent type 肯定是有自己作用的 static 变量其实就是把它所在的 class 看做一个 namespace,它自己是这个 namespace 下的变量,对比一下全局变量和 namespace 中的“全 namespace 变量”就明白了 |
14
wutiantong 2019-04-12 10:01:40 +08:00
@GeruzoniAnsasu 很深入的回复,其实还可以提一下 ADL。。。
|
15
wutiantong 2019-04-12 10:15:57 +08:00
学编程还是别“百度一下”了,直接上 https://stackoverflow.com 应该不用翻墙
|
16
codechaser OP @GeruzoniAnsasu 感谢!因为之前主要用 python 和 java,最近转学 c++,照着写代码总感觉这个"::"充满不解😂
|
17
codechaser OP @wutiantong 百度一下只是习惯😁
|
18
LGA1150 2019-04-19 19:41:00 +08:00
@wutiantong 然而 StackOverflow 的图床 Imgur 被墙了
|