effective C ++ 学习笔记之 item 31 将文件间的编译依赖关系降至最低(未完成)
1. 由于本例中使用了 boost 的shared_ptr,先看一个shared_ptr:shared_ptr使用的是引用计数方式
#include <string>
#include <iostream>
#include <boost/shared_ptr.hpp>
using namespace std;
class implementation
{
public:
~implementation()
{
cout << "析构函数" << endl;
}
void f()
{
cout << "函数f()" << endl;
}
};
int main()
{
boost::shared_ptr<implementation> sp1(new implementation());
cout << "use_count():" << sp1.use_count() << endl;
boost::shared_ptr<implementation> sp2 = sp1;
cout << "use_count():" << sp2.use_count() << endl;
sp1.reset();
cout << "use_count():" << sp2.use_count() << endl;
return 0;
}
2. 关于前向声明的使用:一般尽量使用指针
#include <iostream>
using namespace std;
class A;
class B
{
public:
B(A *a1);
void f();
private:
A *a;
};
class A
{
public:
A(string name)
{
this->name = name;
}
void d()
{
cout << name << endl;
}
string name;
};
void B::f()
{
cout << a->name << endl;
//cout << a.name << endl; a 是一个指针
//cout << a->d() << endl;
//cout << a.d() << endl;
}
B::B(A *a1)
{
a = a1;
}
int main()
{
A a("hello");
A *p = &a;
B b(p);
b.f();
return 0;
}
如果上面的A中的name是private的,使用a.name也会报错
error: 'std::string A::name' is private,这是因为name是private,出了A的作用域了
另外还有一个前向声明的问题:
class B;
class A
{
public:
void f(B b);
};
class B
{
public:
void g(A a);
};
//上面的是可以的,下面的不行,也就是说做形参可以(返回值也行)
class A;
class B
{
A x;
}
class A
{
B y;
};
因为前向声明并没有给出类的定义,此时只能定义指针和引用,也就是上面的例子的那样,不能定义对象,可以作为形参,因为没有定义对象,而第2个定义对象了
但是一个例外是使用static,静态的数据成员不再类内部,在静态存储区,因此类体有完整的定义,可以创建对象
例如下面的就可以通过编译
#include <iostream>
using namespace std;
class B;
class A
{
public:
void f()
{
cout << "A::f()" << endl;
}
private:
static B b;
};
class B
{
public:
void f()
{
cout << "B::f()" << endl;
}
private:
A a;
};
int main()
{
A a;
B b;
return 0;
}
但是如果是作为构造函数的参数是不能通过的,因为构造函数是创建对象的时候调用的
另外一个前向声明的问题,下面代码中第8行,A中如果没有构造函数A(){}就会报错,B()中可以没有,这与static静态成员变量有关
1 #include <iostream>
2
3 using namespace std;
4 class B;
5 class A
6 {
7 public:
8 A(){} //如果没有A(){}默认的构造函数而出现 error: no matching function for call to 'A::A()'
9
10
11 A(string name)
12 {
13 name_a = name;
14 }
15
16 void f()
17 {
18 cout << "A::f()," << name_a << endl;
19 }
20 private:
21 static B b;
22 string name_a;
23 };
24 class B
25 {
26 public:
27 //但是B中就可以没有B() {}
28 B(string name)
29 {
30 name_b = name;
31 }
32
33 void f()
34 {
35 cout << "B::f()," << name_b << endl;
36 }
37 private:
38 A a;
39 string name_b;
40 };
41 int main()
42 {
43 A a("helloa");
44 B b("hellob");
45 a.f();
46 b.f();
47
48 return 0;
49 }
下面的将static注释掉,则运行正确!如下:
#include <iostream>
using namespace std;
class B;
class A
{
public:
// A(){} //如果没有A(){}默认的构造函数而出现 error: no matching function for call to 'A::A()'
A(string name)
{
name_a = name;
}
void f()
{
cout << "A::f()," << name_a << endl;
}
private:
// static B b;
string name_a;
};
class B
{
public:
//但是B中就可以没有B() {}
B(string name)
{
name_b = name;
}
void f()
{
cout << "B::f()," << name_b << endl;
}
private:
// A a;
string name_b;
};
int main()
{
A a("helloa");
B b("hellob");
a.f();
b.f();
return 0;
}
原因是static在静态存储区,是可以创建对象的,有完整定义,但是也是到用的时候才创建
3. 接口与实现分离的简单例子,下面将struct换成class就不行了
#include <iostream>
using namespace std;
struct Interface
{
void (*f)();//定义一个指针函数
};
void f1()
{
cout << "f1()" << endl;
}
void f2()
{
cout << "f2()" << endl;
}
int main()
{
Interface a;
a.f = f1;
a.f();
a.f = f2;
a.f();
return 0;
}
一个不会敲代码的程序员