扬州大学物理学院c++复习大纲
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
1.名字空间:namespace XXX;
作用域运算符::
using namespace XXX;
#include <iostream.h>
等同于
#include <iostream>
Using namespace std;
2.new和delete
普通变量
p=new int;
*p=5;
等价于
p=new int(5);
数组
#include <iostream.h>
void main()
{int *p;
p=new int[5];
for(int i=0;i<5;i++)p[i]=i*i;
for(i=0;i<5;i++)cout<<p[i]<<" ";
cout<<endl;
delete []p;
}
结果:0 1 4 9 16
3运算符
::x可以作为全局变量
4.引用运算、取地址
#include <iostream.h>
void main()
{int a;
int &m=a;
int *b=&m;
a=5;
cout<<"m="<<m<<" b="<<b<<endl;
m=9;
cout<<"a="<<a<<" b="<<b<<endl;
}
引用,用于在程序的不同部分使用两个以上的变量名指向同一地址(内存空间),使得对其中任一个变量的操作实际上都是对同一地址单元进行的。
被声明为引用类型的变量名则是实际变量名的别名。
引用运算符为&,声明引用的一般形式为:数据类型&引用变量名= 变量名;
对引用进行操作,实际上就是对被引用的变量进行操作;引用不是值,不占存储空;;引用一旦被初始化,就不能再重新赋值。
11点说明:
(1)在一行上声明多个引用型变量(函数)名时,要在每个变量(函数)名前都冠以“&”符号。
(2)引用不是变量,所以引用本身不能被修改(不能再改变成为另一个变量的引用)。
(3)一个变量被声明为引用时必须进行初始化,除非这个引用是用作函数的参数或返回值,为引用提
供的初始值应为变量(包括对象)。
引用一旦被初始化,就不能再重新赋值。
(4)由于引用不是变量,所以,不能说明引用的引用,也不能说明数组元素的类型为引用数组,或指
向引用的指针(引用不占内存空间)。
(5)引用与指针不同
指针的内容或值是某一变量的内存单元地址,而引用则与初始化它的变量具有相同的内存单元地址。
(6)引用运算符和地址运算符不同。
(7)可以用一个引用初始化另一个引用。
(8)常把函数的参数说明成引用以建立函数参数的引用传递方式。
(9)有空指针,无空引用
(10)引用不能用数据类型来初始化。
(11)返回引用的函数调用可作为左值
5.const
#include <iostream.h>
const double PI=3.1415926;//#define PI 3.1415926
int max(const int*p);//在函数参数中使用const
void main()
{int a[5]={21,3,55,12,9};
cout<<PI<<endl;
cout<<max(a)<<endl;
}
int max(const int*p)
{int max=0;
for(int i=0;i<5;i++)if(p[i]>max)max=p[i];
return max;}
结果:3.14159
55
(1)使用const修饰符定义常量时,必须初始化
(2)常量一旦被定义,在程序中任何地方都不能再更改。
(3)如果用const定义的是一个整型常量,int可以省略。
(4)与#define定义的常量有所不同,const定义的常量可以有自己的数据类型,这样C++编译程序可以进行更加严格的类型检查,具有良好的编译时的检测性。
(5)函数参数也可以用const说明,用于保证实参在该函数内部不被改动。
例如,通过函数max求出整型数组a[100]中的最大值,函数原型应该是:
int max(const int* pa);
这样做的目的是确保原数组的数据不被破坏,即在函数中对数组元素的操作只许读,不许写。
6.带缺省参数的函数+函数重载
#include <iostream.h>
void ff(int a,int b,int c=15,int d=45)
{cout<<"a="<<a<<",b="<<b<<",c="<<c<<",d="<<d<<endl;};
void main()
{ff(1,2);
ff(1,2,3);
ff(1,2,3,4);
}
结果:a=1,b=2,c=15,d=45
a=1,b=2,c=3,d=45
a=1,b=2,c=3,d=4
在函数说明中为形参指定一个缺省值,则称此函数为带缺省参数的函数。
当函数调用发生后,在形参表中等号后的各“缺省值”将起实参的传递作用。
如果函数有多个缺省参数,则缺省参数必须是从右向左定义,并且在一个缺省参数的右边不能有未指定缺省值的参数。
函数调用时,参数不带缺省值。
7.函数重载
#include <iostream.h>
void fn( int a,int b)
{cout<<a*b<<endl;};
void fn(int a,int b,int c)
{cout<<a+b+c<<endl;};
void main()
{fn(1,2);
fn(1,2,3);
}
结果:2
6
C++编译系统允许为两个或两个以上的函数取相同的函数名,但是形参的个数或者形参的类型不应相同(不涉及函数的返回值类型),编译系统会根据实参和形参的类型及个数的最佳匹配,自动确定调用哪一个函数,这就是所谓的函数重载。
8.类的定义
class T date
{public:
void Set(int m,int d,int y);
void Print();
private:
int month;
int day;
int y ear;
};
外联函数定义
内联函数的定义
一般情况下,一个模块由规范说明和实现两部分组成。
模块中的说明部分作为一个单独的文件存放起来,这个文件被称为头文件,其扩展名为“.h”;而实现部分可能由多个扩展名为“.cpp”的文件组成。
一般一个较大的文件可以分为三个文件来存放:
(1) 将类的说明作为一个头文件来存放。
内联函数原型和定义一般归入头文件;
(2) 类的实现部分单独组成一个文件,用来存放类的成员函数的定义;
(3) 在main()中实现类的应用。
9.对象
定义
class T date
{ 。
} dot1,dot2,*P=& dot1;
或者使用时
Tdate dot1,dot2, *P=& dot1;
成员访问:
对象名.公有成员
指向对象的指针 成员或(*对象指针名).公有成员对象的引用.成员
10.this指针
void Tdate::set(int m,int d,int y)
{month=m; day=d; y ear=y;}
等同与如下写法:
void Tdate::set(int m,int d,int y)
{this->month=m; this->day=d; this->year=y;}
11.构造函数
无参构造函数和有参构造函数
#include <iostream.h>
class test
{private:
int num;
float f1;
public:
test();
test(int n, float f);
} ;
test::test()
{num=0;
f=1.2;
cout<<"Default"<<endl;
}
test::test(int n, float f)
{ num=0;
f=1.2;
cout<<"n="<<n<<",f="<<f<<endl;
}
void main()
{ test x;
test y(10, 21.5);
}
结果:Default
n=10,f=21.5
拷贝构造函数
class cat
{private:
int age;
public:
cat();
cat(cat &);};
cat::cat(cat &other)
{age=other.age;
}
拷贝构造函数
拷贝构造函数的功能是用一个已有的对象来初始化一个被创建的同类对象,是一种特殊的构造函数,具有一般构造函数的所有特性,当创建一个新对象时系统自动调用它;其形参是本类对象的引用,它的特殊功能是将参数代表的对象逐域拷贝到新创建的对象中。
用户可以根据自己实际问题的需要定义特定的拷贝构造函数,以实现同类对象之间数据成员的传递。
如果用户没有声明类的拷贝构造函数,系统就会自动生成一个缺省拷贝构造函数,这个缺省拷贝构造函数的功能是把初始对象的每个数据成员的值都复制到新建立的对象中。
自动调用的4种情况
1、用类的一个对象去初始化另一个对象
2、用类的一个对象去初始化另一个对象时的另外一种形式
3、对象作为函数参数传递时,调用拷贝构造函数。
4、如果函数的返回值是类的对象,函数调用返回时,调用拷贝构造函数。
拷贝构造函数分为两种,深拷贝和浅拷贝构造函数。
由C++提供的默认拷贝构造函数是浅拷贝复制(逐个成员依次拷贝),即只复制对象空间而不复制资源。
数组是可以用浅拷贝的.
如果对象的数据成员包括指向堆空间的指针,就不能使用浅拷贝方式。
深拷贝需要同时复制对象的空间和资源。
12.基本数据类型转换为类类型
class A
{public:
A();
A(int);
};
f(A a) // f函数的定义;f函数的形参为A类的对象
f(1); /*f函数的调用;进行f函数调用时先构造一个A类对象,调用A::A(int)
类类型向基本型转换
#include<iostream.h>
class RMB
{public:
RMB(double value = 0.0);
operator double()
{return yuan + jf / 100.0;}
void display()
{cout << (yuan + jf / 100.0) << endl; } protected:
unsigned int y uan;
unsigned int jf;
};
RMB::RMB(double value)
{yuan = value;
jf = ( value - yuan ) * 100 + 0.5;}
void main()
{RMB d1(2.0), d2(1.5), d3;
d3 = ((double)d1 + (double)d2);
d3.display();
d3 = d1 + d2;
d3.display();
}
13.析构函数
#include <iostream.h>
#include <string.h>
class Student
{public:
Student(char* pName="no name")
{strncpy(name,pName,40);
name[39]= '\0';
cout <<pName <<endl;}
Student(Student& s)
{cout <<"copy of "<< <<endl;
strcpy(name, "copy of ");
strcat(name,);}
~Student()
{cout <<"~student " <<name <<endl;} protected:
char name[40];};
void fn(Student s)
{cout <<"fn()\n";}
void main()
{Student randy("Randy");
Student wang("wang");
cout <<"Calling fn\n";
fn(randy);
cout <<"Returned from fn()\n";
}
结果:Randy
wang
Calling fn
copy of Randy
fn()
~student copy of Randy
Returned from fn()
~student wang
~student Randy
通过结果看析构函数和构造函数的调用顺序
14.对象成员
构造函数先客人后自己
析构函数先自己后客人
15.静态数据成员
#include<iostream.h>
class T
{static int i;
public:
T(){i++;}
int list(){return i;}
};
int T::i=0;
void main()
{T a,b;
cout<<a.list()<<" "<<b.list()<<endl;
}
结果: 2 2
静态数据成员被存放在内存的某一单元内。
即使没有创建任何一个该类对象,类的静态成员在存储空间中也是存在的,可以通过类名::或对象名. 访问(如果静态数据成员是public的,否则用成员函数访问)。
含有静态数据成员的类在创建对象时不为静态数据成员分配存储空间,可以将静态数据成员看成是一个全局变量,将其封装在某个类中通常有两个目的:
(1) 限制该变量的作用范围。
例如将其放在类的私有部分声明,则它只能由该类对象的函数成员直接访问。
(2) 将意义相关的全局变量和相关的操作物理地放在一起,可以增加程序的可读性和可维护性。
初始化在类体外进行。
其格式如下:
<数据类型><类名>::<静态数据成员名>=(初始值);
16.静态成员函数
(1) 函数也可以声明为static的。
静态成员函数无this指针,它是同类的所有对象共享的资源,只有一个共用的副本,它不能直接访问非静态的数据成员,必须要通过某个该类对象才能访问。
(2) 在静态成员函数中访问的一般是静态数据成员或全局变量。
(3)由于静态成员函数属于类独占的成员函数,因此访问静态成员函数的消息接收者不是类对象,而是类自身。
在调用静态成员函数的前面,必须缀上对象名或类名,经常用类名。
(4) 一个类的静态成员函数不需要创建任何该类的对象就可以被调用。
但一般不这么做。
(5) 静态成员函数不能是虚函数,若非静态成员函数和静态成员函数具有相同的名字和参数类型将是非法的17.友元函数
#include <iostream.h>
class myclass
{ int x,y;char *string;
public:
myclass(int x1,int y1);
friend int sum(myclass c);
friend void print(myclass c);};
myclass::myclass(int x1,int y1)
{x=x1;y=y1;}
int sum(myclass c)
{return c.x+c.y;}
void print(myclass c)
{ cout<<"x="<<c.x<<" y="<<c.y<<endl;}
void main()
{myclass c(10,10);
cout<<"the sum is:"<<sum(c)<<endl;
print(c);
}
结果:the sum is:20
x=10 y=10
友元函数是一种说明在类定义体内的非成员函数:friend 〈返回值类型〉〈函数名〉(〈参数表〉);
(1)友元函数是在类中说明的一个函数,它不是该类的成员函数,但允许访问该类的所有成员。
它是独立于任何类的一般的外界函数。
友元并不在类的范围中,它们也不用成员选择符(.或->)调用,除非它们是其它类的成员。
(2)友元没有this指针,访问该类的对象的成员时,必须使用对象名,而不能直接使用类的成员名。
(3)虽然友元函数是在类中说明的,但其名字的作用域在类外,作用域的开始点在说明点,结束点和类名相同。
(4)如果在说明友元时给出了该函数的函数体代码,则它是内联的。
(5)在类外定义友元函数时去掉friend关键字。
友元成员
#include<iostream.h>
#include<string.h>
class P;
class add
{int x,y,z;
public:
add(int a,int b,int c){x=a;y=b;z=c;}
void show(P&);};
class P
{int n;
public:
P(int m){cout<<"a+b+c=";n=m;};
friend void add::show(P&);
};
void add::show(P& m)
{cout<<x+y+z<<endl;cout<<"m="<<m.n<<endl;}
void main()
{ P aa(12);
add bb(10,20,15);
bb.show(aa);
}
结果:a+b+c=45
m=12
另一个类的成员函数可以作为某个类的友元,只是在声明友元函数时要加上成员函数所在的类名,称为友元成员。
声明如下:friend 函数返回值类型类名∷成员函数名(形参列表);
friend授权该函数可以访问宣布其为友元的类中的所有成员。
友元类
#include<iostream.h>
class P
{int n;
friend class add;
public:
P(int m){cout<<"a+b+c=";n=m;};
};
class add
{int x,y,z;
public:
add(int a,int b,int c){x=a;y=b;z=c;}
void show(P&);};
void add::show(P& m)
{cout<<x+y+z<<endl;cout<<"m="<<m.n<<endl;}
void main()
{ P aa(12);
add bb(10,20,15);
bb.show(aa);
}
结果:a+b+c=45
m=12
某一个类可以是另一个类的友元,这样作为友元的类中的所有成员函数都可以访问另一个类中的私有成员。
友元类的说明方式如下:
friend class 〈类名〉;
18.继承、派生新类过程
派生类具有如下特点:
(1) 新的类可在基类的基础上包含新的成员;
(2) 在新的类中可隐藏基类的成员函数;
(3) 可为新类重新定义成员函数。
基类与派生类的关系如下:
(1) 派生类是基类的具体化。
(2) 派生类是基类定义的延续。
(3) 派生类是基类的组合。
派生类定义:
class 派生类名:继承方式基类名
1)吸收基类成员
(2)改造基类成员
一是依靠派生类的继承方式来控制基类成员的访问。
二是对基类数据成员或成员函数的屏蔽(覆盖),即在派生类中定义一个和基类数据成员或成员函数同名的成员。
但是基类的成员并不是被替换了,如果想调用可以使用::运算。
(3)添加新的成员
#include<iostream.h>
class A
{private:
int m;
public:
A(int a,int b)
{m=a+b;}
int R()
{return m;}
};
class B:public A
{int n;
public:
B(int a,int b,int m=0):A(a,b)
{n=m;}
int R()
{return A::R();}
int R2() {return m;} //private,protected需要加这句话
};
void main()
{B ss(10,15,12);
cout<<ss.R2()<<","<<ss.R()<<endl;
}
19.派生类的构造函数
#include<iostream.h>
class data
{int x;
public:
data(int x)
{cout<<"class data\n";}
};
class a
{data d1;
public:
a(int x):d1(x)
{cout<<"class a\n";}
};
class b:public a
{data d2;
public:
b(int x):a(x),d2(x)
{cout<<"class b\n";}
};
class c:public b
{public:
c(int x):b(x)
{cout<<"class c\n";}
};
void main()
{c ss(5);}
结果:class data
class a
class data
class b
class c
在下面两种情况下,必须定义派生类的构造函数:
1 派生类本身需要构造函数;
2 在定义派生类对象时,其相应的基类对象需调用带有参数的构造函数。
派生类构造函数(参数表):基类构造函数(参数表),对象成员1 (参数表)……,对象成员n (参数表)
{派生类新增成员的初始化语句;}
在定义派生类对象时构造函数的执行顺序是先祖先(基类,调用顺序按照它们继承时说明的顺序),再客人(对象成员,调用顺序按照它们在类中说明的顺序),后自己(派生类本身)。
20.赋值兼容规则
所谓赋值兼容规则就是在公有派生的情况下,一个派生类的对象可以作为基类的对象来使用的地方(在公有派生的情况下,每一个派生类的对象都是基类的一个对象,它继承了基类的所有成员并没有改变其访问权
具体的说,有三种情况可以把一个公有派生类的对象作为基类对象来使用:
(1) 派生类对象可以赋给基类的对象。
如:(约定类derived是从类base公有派生而来的)
derived d;
base b(d);
(2) 派生类对象可以初始化基类的引用。
如:
derived d;
base &br=d;
(3) 派生类对象的地址可以赋给指向基类的指针。
如:
derived d;
base *pb=&d;
21.多继承的概念
class<派生类名>:[继承方式]基类名1,[继承方式]基类名2, ...,[继承方式]基类名n
{// 定义派生类自己的成员;};
重继承可以看作是单一继承的扩展,单继承可以看作是多继承的一个最简单的特例。
22.虚基类概念
当在多条继承路径上有一个公共的基类,会产生二义性,使用关键字virtual将基类说明成虚基类解决这个问题
23运算符重载
#include<iostream.h>
class P
{public:
P(int a,int b){x=a;y=b;};
P operator+(P&);
P& operator++();
void OUT(){cout<<"x="<<x<<",y="<<y<<endl;}
protected:
int x,y;
};
P P::operator+(P& a)
{int n=x-a.x;
int m=y-a.y;
P l(n,m);
return l;}
P& P::operator++()
{int i,j=x;
for(i=0;i<j-1;i++)x*=j;
return *this;}
void main()
{P a(5,25);
P b(2,30);
c=a+b;
++c;
c.OUT();
}
结果:x=27,y=-5
把+变成-,++变成阶乘
即x=(5-2)^(5-2)=27
Y=25-30=-5
1. 运算符重载定义
运算符重载是对已有的运算符赋予多重含义,同一个运算符作用于不同类型的数据(对象)导致不同类型的行为。
2. 运算符重载的规则
(1)不能重载的运算符是:
(1) 成员访问运算符. (2)作用域运算符∷(3)条件运算符?:
(4) 成员指针运算符* (5) 编译预处理命令的开始符号#
(2)只能重载c++原有的运算符,重载之后运算符的优先级和结合性都不变。
(3)重载功能不改变原运算符所需操作数的个数
前自增和后自增运算符++的重载
前自增运算符++和后自增运算符++重载的语法
<函数类型>operator++(); //前
<函数类型>operator++(int); //后
24.虚函数
#include<iostream.h>
class A
{ public:
A()
{cout<<"class A"<<endl;
f();
}
virtual void f()
{cout<<"A::f()"<<endl;}
void g()
{cout<<"A::g()"<<endl;}
void h()
{ cout<<"A::h()"<<endl;
f(); g();
}};
class B: public A
{public:
void f()
{cout<<"B::f()"<<endl;}
void g()
{cout<<"B::g()"<<endl;}};
{ A a;
B b;
A *p=&b;
p->f();
p->g();
p->h();
a.f();
a.g();
a.h();
b.f();
b.g();
b.h();
}
结果:
class A // A a;的运行结果
A::f()
class A // B b;
A::f()
B::f() // p->f();
A::g() // p->g();
A::h() // p->h();
B::f()
A::g()
A::f() // a.f();
A::g() // a.g();
A::h() // a.h();
A::f()
A::g()
B::f() // b.f();
B::g() // b.g();
A::h() // b.h();
B::f()
A::g()
指向基类对象的指针都可以指向它的公有派生类对象(不能指向私有派生类对象)。
不能将指向派生类对象的指针指向其基类对象。
1.虚函数的定义
在上例中如果想让指针指向基类对象就调用基类的who(),指向派生类对象就调用派生类的who()(不要强制类型转换)。
在基类中将who()函数声明为虚函数即可。
虚函数是一种非静态的成员函数,说明虚函数的方法如下:
virtual 〈类型〉〈函数名〉(〈参数表〉)
(1) 虚函数是在基类和派生类中声明相同而定义不同的成员函数,在派生类中重新定义基类中的虚函数时,
可以不加virtual,因为虚特性可以下传。
(2) 析构函数可以是的虚函数,但构造函数则不能是虚函数。
(3) 在类体系中访问一个虚函数时,应使用指向基类的指针或对基类的引用,以满足运行时多态性的要求。
也可以像调用普通成员函数那样利用对象名来调用一个虚函数。
(4) 在派生类中重新定义虚函数时,必须保证派生类中该函数的返回值和参数与基类中的说明完全一致,否则就属于重载,丢失虚特性。
(5) 若在派生类中没有重新定义虚函数,则派生类的对象将使用其基类中的虚函数代码。
(6) 虚函数必须是类的一个成员函数(不能是友元或静态成员函数)。
(7) 通过指向基类对象的指针调用虚函数时,C++系统对该调用进行动态绑定,而使用普通函数则是静态绑定。
(8) 若派生类中没有再定义基类中已有的虚函数,则指向该类对象的指针或引用名引用虚函数时总是引用距离其最近的一个基类中的虚函数。
虚函数派生类有就用派生类的,没有就用基类的。
(9) 若在基类的构造(析构)函数中也引用虚函数,则所引用的只能是本类的虚函数。
25.纯虚函数
如果基类只表达一些抽象的概念,而并不与具体的对象相联系,但它又必须为它的派生类提供一个公共的界面,在这种情况下,可以将基类中的虚函数定义成纯虚函数。
纯虚函数是一种没有具体实现的特殊的虚函数。
纯虚函数的定义格式如下:
virtual 〈类型〉(函数名)((参数表))=0;
抽象类
如果一个类至少有一个纯虚函数,那么就称该类为抽象类。
抽象类不能建立对象。
能够建立对象的类称为具体类,也就是不含纯虚函数的类。
抽象类的主要作用是为其所组织的继承层次结构提供一个公共的基类,它刻划了公有行为的特征,其它类可以从它这里继承和实现接口,纯虚函数的实现由其具体的派生类来提供。
#include<iostream.h>
class M
{public:
virtual int L()=0;
};
class A:public M
{protected:
int x,y;
public:
A(int a,int n)
{x=a;y=n;}
int L()
{int i,j=x;
for(i=0;i<y-1;i++)x*=j;
return x;}
};
void main()
{M *s;
s=new A(2,10);
cout<<s->L()<<endl;
}
结果:1024
26.cout<<和cin>>
a、cout是ostream的对象,<<是运算符重载,函数原型:
ostream& operator<<(int n);
ostream& operator<<(float f);
ostream& operator<<(const char*psz);
b、cin是istream的对象,>>是运算符重载,函数原型:
istream& operator>>(float &f);
istream& operator>>(int &n);
istream& operator>>(char*psz);
27.异常处理概念
C++语言异常处理用3个保留字实现:throw、try和catch。
含义如下:
(1) try:标识程序中异常语句块的开始。
(2) throw:用来创建用户自定义类型的异常。
(3) catch:标识异常处理模块的开始。
try
{// try语句块,其中包括throw语句抛出异常}
catch(类型1 参数1)
{// 针对类型1的异常处理}
catch (类型n 参数n)
{// 针对类型n的异常处理}
28.windows编程概念
Windows系统
多个应用程序同时执行。
多窗口(图形界面)同时活动。
运行机制是“消息传递,事件驱动”
29.API和MFC
Windows API是Windows系统和应用程序间的标准接口,为应用程序提供Windows支持的函数定义、参数定义和消息格式等。
Windows API是应用程序编程接口的英文缩写。
它是大量函数加上数字常量、宏、结构、类型以及其它相关项的集合。
在Windows应用程序中,调用API函数的方法同调用C库函数的方法相同,重要区别是C库函数的目标代码直接放到程序目标代码中,而API函数的目标代码则位于程序之外的某个动态链接库(DLL)中。
Windows API是包含在Windows操作系统中的,另外还有单独的驱动程序开发包(DDK),用来开发Windows驱动程序。
因为Windows API函数本身是用C语言编写的。
MFC类库包括用来开发C++应用程序和Windows应用程序的一组类,这些类用来表示窗口、对话框、设备上下文、公共GDI对象如画笔、调色板、控制框和其它标准的Windows部件,封装了大部分的Windows API函数
⏹MFC类库作为C++与Windows的接口,建立在Win32应用程序编程接口API之上,封装了大多数
的API函数,主要是API中与程序结构相关的部分和最常用的部分。
⏹MFC定义了应用程序的轮廓,并提供了用户接口的标准实现方法,程序员所要做的就是通过预定
义的接口把具体应用程序特有的东西填入这个轮廓。
⏹MFC编程最好的办法是使用MFC的应用程序向导AppWizard。
AppWizard为程序员提供了一种快
捷方便的工具来定制生成基于MFC的应用程序框架,程序员只需以此为基础,添加与修改程序代码来实现所需功能。