ANSI/ISO C++ Professional Programmer's Handbook(8)

ANSI/ISO C++标准(第二版) ANSI/ISO C++标准第二版(ISO/IEC 14882:2003) 立即下载
 摘自: http://sttony.blogspot.com/search/label/C%2B%2B

8


命名空间


by Danny Kalev




命名空间(Namespaces)在1995年引入C++标准。本章说明了什么是命名空间以及为什么将加入语言。你将看到命名空间如何避免命名冲突以及在大型工程中命名空间如何推动配置管理和版本控制。最后,你将学习命名空间如何与语言的其他特性结合。


命名空间后面的基本原理


为了理解为什么将命名空间加入语言,这里有一个类比:想象一下如果电脑的文件系统完全没有目录和子目录。所有的文件将存储在一个目录下,在任何时刻每一个用户和应用程序都能看见所有文件。结果,发生了可怕的问题:文件名将冲突(在只允许8.3的文件名的系统中,这更容易发生),列表、拷贝查找文件之类的简单操作都将变得及其困难。另外,安全和授权限制将十分脆弱。


C++的命名空间等价与目录。他们可以很容易的嵌套,他们使你的代码避免命名冲突,他们使你可以隐藏申明,他们不会产生任何运行期开销。C++标准库的大多数组件在命名空间std。命名空间再细分成另外的命名空间比如包含STL重载运算符定义的std::rel_ops。


简要的历史背景


90年代早期,当C++变得日益流行时,许多厂商出售了各种各样组件类的私有实现。字符处理、数学函数和数据容器的类库成为了许多frameworks的一部分MFC、STL、OWL等等。可重用组件的激增导致了命名冲突的问题。例如叫vector的类可能同时出现在数学库和其他容器库中,而这两个库同时被使用;叫string的类在大多数framework和类库都能找到。要求编译器识别两个具有相同名字的类是不可能的。同样的,连接器也不能应付有同样名字的类成员函数。例如,成员函数



vector::operator==(const vector&);

不能定义在两个不同的类中——迪格可能属于数学库,而第二个可能属于容器库。


大型工程更容易受命名冲突的影响


命名冲突不止出现第三方软件库中。在大型软件工程中,类、函数、常量的简短优雅的名字也可能导致命名冲突,因为很可能不同的开发者用相同的名字来表示不同的实体。在没有命名空间的时代,只好在标识符上加上不同的词缀。但这不仅繁琐而且容易出错。考虑下面的代码:



class string //简短但危险。其他人可能已经使用了//这个名字已存在了...
{
//...
};
class excelSoftCompany_string //长的名字安全但冗长。//如果公司改变了名字将是一场恶梦...
{
//...
};

命名空间使你能安全的使用便利、简短、形象的名字。作为笨拙的词缀的替代,你可以将你的申明放在一个命名空间中而不管词缀,就像:



//file excelSoftCompany.h
namespace excelSoftCompany { //命名空间定义
class string {/*..*/};
class vector {/*..*/};
}

命名空间成员与类成员一样,其定义与申明可以分开。例如




#include <iostream>
using namespace std;
namespace A
{
void f(); //申明
}
void A::f() //定义在不同的文件中
{
cout<<"in f"<<endl;
}
int main()
{
A::f();
return 0;
}

命名空间的属性


命名空间更像一个名字容器。他们用于快速简单的移植遗留的代码,而没有任何开销。命名空间有一些使它 更容易使用的属性。下面的章节讨论了这些属性。


完整名字


命名空间是其中申明和定义的范围。为了在其他范围中引用这些申明和定义,需要完整名字(fully qualified name)。标识符的完整名字由三部分组成命名空间,类名字和标识符自己,期间由范围运算符分开(::)。因为命名空间和类的名字都可能嵌套,结果名字可能很长——但是确保了唯一性:



unsigned int maxPossibleLength =
std::string::npos; //完整名字。npos是string的一个成员;//string属于命名空间std
int *p = ::new int; //区别全局new和重载的new

但是,重复完整名字是冗长、没有必要的。你可以使用 using declaration或using directive。


using Declaration和using Directive


一个using申明由关键字using和紧接着的namespace::member组成。它指示编译器将遇到的标识符限制在指定的命名空间中,就像完整命名一样。例如



#include <vector> //STL vector;在命名空间std中定义
int main()
{
using std::vector; //using申明;遇到的每一个vector//都在std中查找
vector <int> vi;
return 0;
}

另一方面,using指示为指示范围内所有可访问的名字指定了命名空间。它有下列序列组成:using namespace接着的是命名空间的名字。例如



#include <vector> //属于命名空间std
#include <iostream> //iostream类和运算符也在命名空间std内
int main()
{
using namespace std; //using-directive;所有<iostream> 和<vector> //申明现在都可见了
vector <int> vi;
vi.push_back(10);
cout<<vi[0];
return 0;
}

回头看一看string类的例子(为了方便在这里重复这个例子):



//文件excelSoftCompany.h
namespace excelSoftCompany
{
class string {/*..*/};
class vector {/*..*/};
}

现在可以在同样的程序中像标准的string一样来使用自己的string,看下面的代码:



#include <string> // std::string
#include "excelSoftCompany.h"
int main()
{
using namespace excelSoftCompany;
string s; //引用类excelSoftCompany::string
std::string standardstr; //现在实例化的是一个ANSI string
return 0;
}

命名空间可以扩展


C++标准化委员会意识到相关联的申明可以跨越好几个translation units。所以命名空间可以定义一部分。例如



//文件proj_const.h
namespace MyProj
{
enum NetProtocols
{
TCP_IP,
HTTP,
UDP
}; // enum
}
//文件proj_classes.h
namespace MyProj
{ // 扩展了命名空间MyProj
class RealTimeEncoder{ public: NetProtocols detect(); };
class NetworkLink {}; //全局的
class UserInterface {};
}

在分开的文件中,一样的命名空间可以通过附加申明扩展。


完整的命名空间MyProj可以由两个文件引出就像下面这样:



//文件app.cpp
#include "proj_const.h"
#include "proj_classes.h"
int main()
{
using namespace MyProj;
RealTimeEncoder encoder;
NetProtocols protocol = encoder.detect();
return 0;
}

命名空间的别名


就像你观察到的,命名空间短的名字最终导致命名冲突。但是过长的命名空间不容易使用。为了这个目的,使用命名空间别名(namespace alias)。下面的例子为笨拙的Excel_Software_Company命名空间定义了别名ESC。命名空间的别名还有其他用途,就像你将看到的。



//文件decl.h
namespace Excel_Software_Company
{
class Date {/*..*/};
class Time {/*..*/};
}
//文件calendar.cpp
#include "decl.h"
int main()
{
namespace ESC = Excel_Software_Company; //ESC是Excel_Software_Company
//的别名
ESC::Date date;
ESC::Time time;
return 0;
}

Koenig查找


Andrew Koenig,C++的创建者之一,为解决命名空间成员的查找问题设计了一种算法。这种算法也叫参数依赖查找(argument dependent lookup),现在为所有适应标准的编译器用来处理下面情况:





警告:有些现存的编译器并不完全支持Koenig查找。因此,下面的程序——依赖于Koenig 查找——在并不完全支持ANSI/ISO标准的编译器下可能不能编译通过。




namespace MINE
{
class C {};
void func;
}
MINE::C c; //类型为MINE::C的全局对象
int main()
{
func( c ); //OK,调用了MINE::f
return 0;
}

在程序中既没有使用using申明也没有使用using指示。但是,编译器做了正确的事情——通过应用Koenig查找,它正确的将未加限制的func识别为在命名空间MINE中申明的函数。


Koenig查找指示编译器不仅仅在平常应该找的地方,比如局域范围内查找,还要在包含参数类型的命名空间中查找。因此接着的代码行中检查函数func()的参数对象c,c属于命名空间MINE。编译器将命名空间MINE视为在func()的申明之中,“猜”出了程序员的意图:



func( c ); // OK,调用MINE::f

没有Koenig查找的话,命名空间将给程序员不想接受的麻烦,程序员不得不重复完整名字或使用许多using申明。为了进一步将参数推给Koenig查找,考虑下面的例子:



#include<iostream>
using std::cout;
int main()
{
cout<<"hello"; //OK,通过Koenig查找运算符<<被带到了范围里面
return 0;
}

using申明将std::cout注入main()的范围中,从而使程序员可以使用未加限制的cout。然而,你可能想起重载运算符<<不是std::cout的成员。它是在命名空间std内定义的友元函数,它接受一个std::ostream对象作为参数。没有Koenig查找,程序员不得不写成下面的形式:



std::operator<<(cout, "hello");

作为选择,程序员也可以提供using namespace std;指示。然而没有一种方法是领人赏心悦目的,因为他们使代码散乱而且是混淆和错误的源头。(using指示至少有利于使名字在当前范围可见,因为他们使得命名空间的所有成员不加区别的都可见了)。幸运的是,Koenig查找“做了正确的事情”,以文雅的方式使你从这些烦劳中解脱出来。


Koenig查找是自动使用的。激活它不需要特殊的指示或配置开关,也没有办法关闭它。必须时刻注意这个事实,因为在有些情况下它可能带来令人吃惊的结果。例如



namespace NS1
{
class B{};
void f;
};
void f(NS1::B);
int main()
{
NS1::B b;
f; //不明确;NS1::f()还是f(NS1::B)?
return 0;
}

对于这种情况,适应标准的编译器一定会给出错误。但是不符合标准的编译器不会指出调用的不明确;他们简单的选择f()的一个版本。这可能是程序员不想要的结果。此外,问题可能发生在开发的后期,在工程中加入f()的附加版本的时候——可能妨碍编译器的查找算法。这种不明确不仅仅限制在全局名字。它也可能出现在两个命名空间互相有关的时候——例如,命名空间申明的类,而类被在不同命名空间申明的类成员函数作为参数。


命名空间实践


从前面的例子中可以总结出,和语言其他特性一样必须明智的使用命名空间。对于只包含少数类和几个源文件的小工程,命名空间是不需要的。在大多数情况下,这样的程序由一个程序员编码和维护,他们使用的组件数目有限。命名空间的可能性很小。如果还是出现了命名冲突,一般是重命名存在的类或函数,或简单的在后面增加命名空间。


另一方面,大型工程——如前面说明的——更容易受到命名冲突的影响;因此他们需要系统的命名空间。有上百程序员合作的工程或许多开发小组一起合作的大项目十分常见。例如Microsoft Visual C++ 6.0的开发历时18个月,超过1000的程序员与开发过程有关。管理这样的大型工程需要良好文档的编码方针——命名空间正是这样一个工具。


在大型工程利用命名空间的方针


为了展示命名空间如何在结构管理中应用,假象一个国际信用卡公司的在线事务处理系统。项目由好几个开发小组组成。其中数据库管理小组负责创建和维护数据库的表、索引和访问授权。数据小组也必须提供访问例程和对数据库中数据进行检索、操作的数据对象。第二个小组负责图形用户界面(GUI)。第三个小组处理来自电影院、饭店、商店以及任何旅行者可能使用他们的国际Unicard付帐的地方提出的国际在线请求。在每个信用卡的所有者交易之前,每一个购买,电影票、珠宝或艺术书都必须通过Unicard确认。每个确认的过程检查信用卡的有效性、它的有效期限和信用卡所有者的收支平衡。对于国内购买有一个相似的确认过程。但是,国际确认要求用卫星传送,而国内确认一般使用电话。


在软件项目里,代码的可重用性是十分重要的。因为,同样的处理逻辑同时适用与国内和国际确认,所以检索相关信息和执行必要计算的数据库访问对象应该是相同的。虽然如此,国际确认还需要经常使用通讯协议堆栈,以接收通过卫星传过来的请求,解释它再返回发送者一个加密的回答。基于卫星确认的典型实现可以是将数据库访问对象和必要的通讯对象捆绑在一起,通讯对象封装了协议、通讯层、优先权管理、消息队列、加密和解密等过程。不难想象通讯对象和数据库访问对象同时使用了一个名字而引起了命名冲突。


例如,两个对象——一个封装了数据库连接而另一个指的是卫星连接——可能有同样的名字:Connection。但是如果通讯组件和数据库访问对象申明在两个不同的命名空间中,潜在的命名冲突将减至最小。因为,com::Connection和dba::Connection可以在同一个应用程序中同时使用。系统的方法可以是给每一个小组分配一个独立的命名空间。这样的方针可以帮助你在不同的小组以及第三方代码中避免命名冲突。


命名空间和版本控制


成功的软件项目不会只有一个版本。在大多数项目中,基于前辈的新版本不断发布。此外,前一个版本必须支持打补丁和调整以适应新的操作系统、新的应用环境和新的硬件。Web浏览器、商业数据库、字处理软件和多媒体工具就是这样的例子。同样的开发小组必须对同一软件产品的不同版本提供支持是一种常见情况。大量的软件能共享同样产品的不同版本,但是每一个版本也有它特殊的组件。这种情况下可以使用命名空间别名迅速从一个版本切换到另一个版本。


一般连续项目有一些经常使用的基础软件组件。另外,每一个版本有自己独有的特殊组件。命名空间别名可以提供动态命名空间(dynamic namespaces);命名空间别名可以指给定时间的版本X的命名空间,在其他时候、它也可以指不同的命名空间。例如



namespace ver_3_11 //16 bit
{
class Winsock{/*..*/};
class FileSystem{/*..*/};
};
namespace ver_95 //32 bit
{
class Winsock{/*..*/};
class FileSystem{/*..*/};
}
int main()//实现16 bit版
{
namespace current = ver_3_11; //current是 ver_3_11的别名
using current::Winsock;
using current::FileSystem;
FileSystem fs; // ver_3_11::FileSystem
//...
return 0;
}

在这个例子中,别名current是一个可以指ver_3_11也可以指ver_95的符号。为了在不同版本之间切换,程序员仅仅只需要将不同的命名空间赋值给它。


命名空间不会带来额外的开销


命名空间的实现包括Koenig查找都是静态的。命名空间的底层实现使用名字分裂(name mangling),就是编译器通过函数的参数列表,函数的类名以及函数的命名空间名字来合成出函数的独一无二的名字(参见第十三章“C语言的兼容性问题”,有名字分裂的具体细节)。因此,命名空间不会成生运行时间和内存的开销。


命名空间和语言其他特性的互相影响


命名空间和语言的其他特性结合影响了程序设计技术。命名空间使得C++中的有些特性变的可有可无或是不受欢迎。


不需用范围运算符来指定全局变量


在一些frameworks(例如MFC),它习惯于加范围运算符到全局函数前面来显式的指明,这是全局函数而非类成员函数(象下面的例子那样):



void String::operator = (const String& other)
{
::strcpy (this->buffer, other.getBuff());
}

这种习惯使不推荐的。许多曾经是全局函数的标准函数现在都被归到命名空间内部了。例如,现在strcpy属于命名空间std,大多数标准库的函数都是如此。前面那些有范围运算符的函数可能使编译器的查找算法混淆;另外,这样做破坏了分割全局命名空间的思想。因此,不推荐你在函数名之前加上范围运算符。


将外部函数变为文件内函数


在标准C中,没有申明为静态的非局域变量有内部连接(internal linkage),这意味着仅仅在同一translation unit中申明的才是可见的(参见第二章“标准简报:ANSI/ISO C++的最新附加部分”)。这种技术用于信息隐藏(如下面的例子):



//File hidden.c
static void decipher(FILE *f); //仅仅在本文件中可见
//现在在当前源文件中使用该函数
decipher ("passwords.bin");
//文件结束

尽管在C++中仍然支持这样,这个习惯现在已成为了反对的特性(deprecated feature)。你编译器未来的版本中,编译器在找到非类成员函数的静态标识符时可能会给出警告。为了使函数只在自己的translation unit中可见,使用未命名命名空间(unnamed namespace)。下面的例子示范了这种用法:



//File hidden.cpp
namespace //未命名
{
void decipher(FILE *f); //仅仅在本文件中可见
}
//现在在当前文件中使用函数
//不需要使用命名空间申明或命名空间指示
decipher ("passwords.bin");

尽管在未命名命名空间中的名字可能需要外部连接(external linkage),他们在其他translation unit中却不可见;产生的效果是在未命名命名空间出现的名字有静态连接(static linkage)。如果你在其他文件的未命名命名空间中申明同名的其他函数,两个函数互相隐藏,把他们不会产生命名冲突。


标准头文件


现在所有的标准C++头文件必须这样包括:



#include <iostream> //注意:没有“.h”扩展

.h扩展被忽略了。标准C头文件也服从这个习惯,只是有一个附加的字母c。因此,以前叫<xxx.h>的C头文件现在叫<cxxx>。例如



#include <cassert> //以前:<assert.h> 注意前缀'c' 和//忽略".h"

C头文件的旧的习惯,<xxx.h>仍然被支持;但是,是被反对的特性,因此在新的C++代码中不使用。原因是C <xxx.h>头文件将其申明的名字加入到了全局命名空间中。然而在C++中,大多数标准申明归到了命名空间std中,像<cxxx>这样的标准C头文件一样。不能从在头文件的物理地址使用的实际命名习惯或它的实际名字得出什么推论。事实上,大多数编译器为<xxx.h>和对应的符号<cxxx>共享一个物理文件。通过一些隐藏的预处理技巧很容易办到。记住你必须使用using申明、using指示或完整名字来访问新风格标准头文件中的申明。例如



#include <cstdio>
using namespace std;
void f()
{
printf ("Hello World/n");
}

命名空间的限制


C++标准给命名空间的使用定义了几条限制。这些限制式为了有意避开可能搞得一团糟的不规则和不明确的地方。


不能改变命名空间std


一般的命名空间是开放的,所以通过交叉在许多文件中的附加申明和定义可以完全合法的扩展命名空间。唯一的例外是命名空间std。根据标准,通过附加申明改变命名空间std的结果——不要动已存在地那个——是为定义的行为,也是不允许的。这条限制可能很武断,但是它只是公共的认识——任何篡改命名空间std的行为破坏了标准申明在专有排外的命名空间中的基本观念。


用户定义的new和delete不能在命名空间中申明


标准禁止在命名空间中申明new和delete运算符。下面的例子说明了为什么:



char *pc; //全局
namespace A
{
void* operator new ( std::size_t );
void operator delete ( void * );
void func ()
{
pc = new char ( 'a'); //使用A::new
}
} //A
void f() { delete pc; } //调用A::delete还是//::delete?

有些程序员可能希望选中运算符A::delete,因为它匹配用来分配内存的new运算符;另一些程序员可能希望选中标准运算符delete,因为A::delete对于函数f()是不可见的。通过禁止在命名空间中申明运算符new和delete,C++避免了这样的麻烦。


总结


命名空间是最新加入C++标准的。因此,有些编译器不完全支持这些特性。不过,所有的编译器厂商将在将来的版本中完全支持命名空间。不必过分强调命名空间的重要性。如你所见,许多著名的C++程序使用了STL的组件、iostream库和其他标准头文件——所有这些都是命名空间的成员。


大型软件项目可以明智的使用命名空间来避免公共缺陷和使得版本控制更容易,就像你已经看到的。


C++提供三种方法,将命名空间的要素加入到当前的范围中。第一种是使用using指示,它将使命名空间的所有成员在当前范围中可见。第二种是使用using申明,它将更有选择性的使命名空间中的单一组件可见。最后一种使用独一无二的完整名字来标志命名空间成员。另外,依赖参数查找或Koenig lookup,不必强迫程序员提及命名空间就可以捕捉程序员的正确意图。


ANSI_ISO C++ Professional Programmer's Handbook 立即下载

相关推荐

Competitive Programmer’s Handbook

The purpose of this book is to give you a thorough introduction to competitive programming. It is assumed that you already know the basics of programming, but no previous background in competitive programming is needed.

转换为ANSI/ISO 标准c++

最近在复习C++,也注意到了 C++ 11新标准的一些动向,微软的msdn也推出了一系列的《welcome back to modern C++ 》的文章,用C++之父Stroustrup的话说,“C++ 11 像一门全新的语言”,(其实真有,D语言基本就是全新的C++),去年研一,花了一个暑假,把《C++ primer plus》厚厚的一本书完完整整地看完了,之后对C++产生了无限的兴

dikang89的专栏 822

利用makehumancommunity导入人体模型到COMSOL里(需要solidwork)

#makehumancommunity #solidwork #COMSOL

qq_41227634的博客 2158

ANSI/ISO C++ Professional Programmer's Handbook 13

ANSI/ISO C++ Professional Programmers Handbook 13与C语言的兼容性问题by Danny Kalev 简介 ISO C 和ANSI/ISO C++的C子集之间的区别 函数形参列表 函数申明 空的形参列

sttony的专栏 1259

时序异常检测汇总

时序异常检测

Mark_Australia的博客 1万+

用电脑通过网口控制keysight示波器

Keysight HD304MSO示波器提供1GHz带宽、14位高精度ADC及10.1英寸触控屏,支持50μV低噪声信号捕获和1.3M波形/秒刷新率。配备4通道探头、逻辑分析仪接口及100Mpts存储深度,含故障诊断、FFT等高级功能。通过网线连接电脑安装TightVNC软件(示波器IP为169.254.163.24)可实现远程控制,相比U盘传输更高效。(149字)

johnboat的专栏 1134

ANSI/ISO C++ Professional Programmer's Handbook 8

ANSI/ISO C++ Professional Programmers Handbook 8命名空间by Danny Kalev 命名空间后面的基本原理 简要的历史背景 大型工程更容易受命名冲突的影响 命名空间的属性

sttony的专栏 798

手把手教你用STM32F030实现功率MOS双脉冲测试(附完整电路图)

本文详细介绍了如何使用STM32F030微控制器搭建功率MOSFET双脉冲测试平台。通过分析双脉冲测试原理,提供了完整的硬件电路设计、驱动电路选型、软件时序生成方法,并指导如何利用示波器捕获和分析开关波形,从而评估功率器件的动态特性与开关损耗。

juice的博客 712

ANSI/ISO C++ Professional Programmer's Handbook 14

ANSI/ISO C++ Professional Programmers Handbook 14总结和未来的方向by Danny Kalev 一些差一点被加入到标准的特性 Hashed联合容器 函数模板的默认类型参数 C++演

sttony的专栏 941

MAS1102量产工具实战指南:从下载到开卡,附固件选择与RDT优化技巧

本文提供MAS1102量产工具的实战指南,涵盖从工具下载、短接识别到开卡操作的全过程。重点解析了固件选择策略与RDT优化技巧,帮助用户成功修复基于联芸MAS1102主控的固态硬盘,解决常见开卡错误并提升SSD性能与稳定性。

c2d3e4f的博客 2191

雨雾天YOLOv8检测拉胯?暗通道去雾+上下文注意力双优化,mAP从58%飙到79%,暴雨也能看清车牌

室外交通监控:高速、省道的雨雾天检测,重点解决小车、货车漏检;车载ADAS系统:雨天行车时的前方车辆、行人识别,需实时性(<40ms);隧道出入口:明暗交界+雾天的复杂场景,暗通道能平衡亮度。

专注于Python爬虫开发,分享爬虫技巧、项目实战与反爬经验,使用Scrapy、BeautifulSoup等工具,解决数据抓取难题。 1380

ANSI/ISO C++ Professional Programmer's Handbook 2

ANSI/ISO C++ Professional Programmers Handbook 2标准简报:ANSI/ISO C++的最新附加部分by Danny Kalev 简介 理解 ANSI/ISO标准 本章的目的和结构 标准的术语

sttony的专栏 1234

利用Python爬虫采集京东商品评论情感分析案例(含完整代码)

在电商蓬勃发展的今天,商品评论蕴含着巨大的商业价值。本文以京东商品评论为研究对象,系统介绍如何使用Python构建一个完整的评论采集与情感分析系统。文章涵盖京东反爬机制分析、动态请求模拟、评论数据解析、中文文本预处理、基于SnowNLP和深度学习的情感极性分类、以及可视化展示等完整技术链路。所有代码均基于2025-2026年最新可用接口编写,并提供可直接运行的完整源码。全文力求详实,总字数逾八千字,适合Python数据分析从业者、电商运营人员及自然语言处理初学者参考实践。目录摘要第一章 引言。

2201_76125261的博客 87

ANSI/ISO C++ Professional Programmer's Handbook 3

ANSI/ISO C++ Professional Programmers Handbook 3 运算符重载by Danny Kalev 简介 运算符重载的唯一规则 成员和非成员 运算符的接口 运算符的一致性

sttony的专栏 845

AES加密算法及AES-CMAC原理白话版系统解析

对AES不同加密算法,加密模式,加密原理,填充算法及AES-CMAC算法的详细系统介绍,帮助大家对AES进行系统掌握。

initiallizer的博客 4068

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

ANSI/ISO C++ Professional Programmer's Handbook 4

ANSI/ISO C++ Professional Programmers Handbook 4 特殊成员函数:默认构造器,拷贝构造器,销毁器和赋值运算符by Danny Kale 简介 构造器 从类的构造器调用对象的成员函数 不需要的构造器(Trivial

sttony的专栏 601

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

ANSI/ISO C++ Professional Programmer's Handbook(9)

 摘自:http://sttony.blogspot.com/search/label/C%2B%2B9Templatesby Danny Kalev简介 类模板 类模板的申明 实例化和特殊化 模板形参 默认类型参数 静态数据成员 友元 部分特殊化 类模板的显式特殊化 类模板函数的特殊化 函数模板 带参数的宏 void

SearchLife的专栏 1050

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

ANSI/ISO C++ Professional Programmer's Handbook(12)

  摘自:http://sttony.blogspot.com/search/label/C%2B%2B12优化你的代码by Danny Kalev 简介 本章的范围 在优化你的软件之前 申明的布局 初始化比赋值好 重新放置申明 成员初始化列表 前缀运算符VS后缀运算符 内联函数 函数调用的开销 内联函数的好处 被申明为内

SearchLife的专栏 1209

ANSI/ISO C++ Professional Programmer's Handbook

[在线阅读 或 下载] ANSI/ISO C++ Professional Programmers Handbook 文件格式: PDF/Adobe Acrobat  

Mobidogs Blog 1120

ANSI/ISO C++ Professional Programmer's Handbook(14)

摘自:http://sttony.blogspot.com/search/label/C%2B%2B14总结和未来的方向by Danny Kalev一些差一点被加入到标准的特性Hashed联合容器函数模板的默认类型参数C++演化过程与其他语言的比较用户的利益"Pay as You Go"将来可能加入C++的特性自动垃圾收集器对象永久化

SearchLife的专栏 1352

ANSI/ISO C++ Professional Programmer's Handbook 10

ANSI/ISO C++ Professional Programmers Handbook 10STL和泛型程序设计by Danny Kalev 简介 泛型程序设计 STL头文件的组织 容器 算法 迭代器

sttony的专栏 1218

ANSI/ISO C++ Professional Programmer's Handbook(1)

  摘自:http://sttony.blogspot.com/search/label/C%2B%2B1简介by Danny KalevC++的起源 带类的C 进入C++ 80年代后期:开放导致的泛滥 ANSI委员会标准的建立 成熟 国际性的标准 委员会的草案和公众的评论 标准的锁定和最终化(Feature Freeze and Fin

SearchLife的专栏 1121

ANSI/ISO C++ Professional Programmer's Handbook 7

ANSI/ISO C++ Professional Programmers Handbook 7运行期类型识别by Danny Kalev 简介 本章的结构 不用RTTI 不要RTTI的支持,虚成员函数也能提供对动态类型的合理层次。一个良好设计的类层次可以为在基类中申明的每

sttony的专栏 1294

ANSI/ISO C++ Professional Programmer's Handbook(13)

 摘自:http://sttony.blogspot.com/search/label/C%2B%2B 13与C语言的兼容性问题by Danny Kalev简介ISO C 和ANSI/ISO C++的C子集之间的区别函数形参列表函数申明空的形参列表隐含的int 申明现在ISO C 做了修订,禁止了隐含int 申明和重复申明全局变量隐含的转换v

SearchLife的专栏 1072

ANSI/ISO C++ Professional Programmer's Handbook 11

ANSI/ISO C++ Professional Programmers Handbook 11内存管理by Danny Kalev 简介 存储的类型 自动存储 静态存储 自由存储

sttony的专栏 881

ANSI/ISO C++ Professional Programmer's Handbook 5

ANSI/ISO C++ Professional Programmers Handbook5面向对象的编程和设计by Danny Kalev 简介 程序设计范例 过程化的程序设计 基于对象的程序设计 面向对象的程序设计

sttony的专栏 893
上一篇: ANSI/ISO C++ Professional Programmer's Handbook(9)
下一篇: ANSI/ISO C++ Professional Programmer's Handbook(7)
SearchLife
博客等级 码龄20年 51粉丝 22原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值