程序片段编程题
1.【问题描述】
基类shape类是一个表示形状的抽象类,area( )为求图形面积的函数。请从shape类派生三角形类(triangle)、圆类(circles)、并给出具体的求面积函数。注:圆周率取3.14
#include<iostream>
#include<cmath>
#define PI 3.14
using namespace std;
class shape
{
public:
virtual float area()=0;
};
int main()
{
shape *p;
triangle t(3,4,5);
circles c(10);
p=&t;
cout<<"triangle area:"<<p->area()<<endl;
p=&c;
cout<<"circles area:"<<p->area()<<endl;
}
这题常规补充三角形的面积公式和圆的面积公式就行了,but我现在C++有点忘记构造函数怎么写了,而且继承的时候public shape我还多添了一个冒号,基本功都不太行辣!
class triangle:public shape
{
int a,b,c;
public:
triangle(int a,int b,int c):a(a),b(b),c(c){}
float area(){
float p=(a+b+c)/2.0;
return sqrt(p*(p-a)*(p-b)*(p-c));
}
};
class circles:public shape
{
int r;
public:
circles(int a):r(a){}
float area(){
return 3.14*r*r;
}
};
2.【问题描述】
定义一个抽象类Base,在该类中定义一个纯需函数virtual void abstractMethod() = 0;派生一个基于Base的派生类Derived,在派生类Derived的abstractMethod方法中输出"Derived::abstractMethod is called",最后编写主函数,其内容如下:
#include<iostream>
using namespace std;
class Base{
public:
virtual void abstractMethod() = 0;
};
class Derived:public Base{
public:
void abstractMethod(){
cout<<"Derived::abstractMethod is called";
}
};
int main()
{
Base* pBase = new Derived;
pBase->abstractMethod();
delete pBase;
return 0;
}
虚函数的继承和正常的继承好像其实差别不大......
class Base{
public:
virtual void abstractMethod() = 0;
};
class Derived:public Base{
public:
void abstractMethod(){
cout<<"Derived::abstractMethod is called";
}
};
程序设计题
1.录入下面程序,并分析结果
#include <iostream>
#include <complex>
using namespace std;
class Base
{
public:
Base() {cout<<"Base-ctor"<<endl;}
~Base() {cout<<"Base-dtor"<<endl;}
virtual void f(int){cout<<"Base::f(int)"<<endl;}
virtual void f(double){cout<<"Base::f(double)"<<endl;}
virtual void g(int i=10){cout<<"Base::g()"<<i<<endl;}
};
class Derived : public Base
{
public:
Derived() {cout<<"Derived-ctor" <<endl;}
~Derived(){cout<<"Derived-dtor"<<endl;}
void f(complex<double>) {
cout<<"Derived::f(complex)"<<endl;
}
void g(int i=20){
cout<<"Derived::g()"<<i<<endl;
}
};
int main()
{
cout<<sizeof(Base)<<endl;
cout<<sizeof(Derived)<<endl;
Base b;
Derived d;
Base *pb=new Derived;
b.f(1.0);
d.f(1.0);
pb->f(1.0);
b.g();
d.g();
pb->g();
delete pb;
return 0;
}
我猜的结果和实际的结果——
事后诸葛亮:
相比之下,我错的地方有:
1.不知道sizeof多大
base类包含虚函数,因此会有一个虚表指针(vptr)。在大多数平台上,指针大小为4字节或8字节(取决于32位或64位系统)。因此,sizeof(Base)的输出通常是 8(64位)或 4(32位)。
2.构造派生类Derived前面是需要先构造基类的,所以开局还会有一个Base-ctor。
3.指针引用到new Derived实际上是需要重新构造一个类的,所以也有Base-ctor,Derived-ctor。但如果是引用到已经有的一个对象,比如d,就不需要重新构造了。
4.程序结束时,局部对象b和d也会被析构,分别调用Base和Derived的析构函数
5.
pb->f(1.0)
的行为
背景
pb
是一个指向Derived
对象的Base
类型指针。f
是一个虚函数,因此会动态绑定到实际对象的类型(即Derived
类)。1.0
是一个double
类型的参数。
动态绑定过程
查找
Derived
类中的f
函数:
cppDerived
类中定义了一个f
函数:复制
void f(complex<double>) { cout << "Derived::f(complex)" << endl; }
但这个函数的参数类型是
complex<double>
,与f(double)
不匹配。(complex<double>
是一个类类型,表示复数。它包含两个double
类型的成员(实部和虚部)。double
是一个基本数据类型,表示双精度浮点数)
查找基类
Base
中的f
函数:
cppBase
类中定义了两个f
函数:复制
virtual void f(int) { cout << "Base::f(int)" << endl; } virtual void f(double) { cout << "Base::f(double)" << endl; }
由于
Derived
类中没有匹配的f(double)
函数,动态绑定会回退到基类的f(double)
。
最终调用:
pb->f(1.0)
调用的是Base::f(double)
,输出:Base::f(double)
6.
背景
pb
是一个指向Derived
对象的Base
类型指针。g
是一个虚函数,因此会动态绑定到实际对象的类型(即Derived
类)。g
函数有一个默认参数。
动态绑定过程
查找
Derived
类中的g
函数:
cppDerived
类中定义了一个g
函数:复制
void g(int i = 20) { cout << "Derived::g()" << i << endl; }
这个函数覆盖了基类
Base
中的g
函数。
默认参数的解析:
默认参数是在编译时解析的,而不是运行时。因此,
pb->g()
的行为取决于pb
的静态类型(即Base
类型)。Base
类型的g
函数的默认参数是10
,因此pb->g()
会使用Base
类的默认参数10
。
最终调用:
pb->g()
调用的是Derived::g
,但使用了Base
类的默认参数10
,输出:Derived::g()10
2.录入下面程序,并分析结果
#include <iostream>
using namespace std;
class Base
{
public:
Base():data(count)
{
cout<<"Base-ctor"<<endl;
++count;
}
~Base()
{
cout<<"Base-dtor"<<endl;
--count;
}
static int count;
int data;
};
int Base::count;
class Derived : public Base
{
public:
Derived():data(count),data1(data)
{
cout<<"Derived-ctor"<<endl;
++count;
}
~Derived()
{
cout<<"Derived-dtor"<<endl;
--count;
}
static int count;
int data1;
int data;
};
int Derived::count=10;
int main()
{
cout<<sizeof(Base)<<endl;//8
cout<<sizeof(Derived)<<endl;//8
Base* pb = new Derived[3];//Base-ctorDerived-ctor*3次
cout<<pb[2].data<<endl;//12
cout<<((static_cast<Derived*>(pb))+2)->data1<<endl;//
delete[] pb;//Derived-dtorBase-dtor*3次
cout<<Base::count<<endl;//
cout<<Derived::count<<endl;//10
return 0;
}
我的分析:
要崩溃了www
解释:
1.Base
类的大小为 4
字节,因为它只包含一个 int
类型的成员变量 data
和一个静态成员变量 count
(静态成员变量不占用对象的内存)。Derived
类的大小为 12
字节,因为它继承了 Base
类的 data
,并新增了两个 int
类型的成员变量 data1
和 data。
2.
在第三个对象构造时,Base::count
的值为 3
,但 Derived
的构造函数中 data
被重新初始化为 Derived::count
的值,即 10。
3.data1
的值被覆盖为一个未定义的值(50331651
),这可能是因为内存未正确初始化或存在其他问题
4.由于 pb
是 Base
类型的指针,编译器只会调用 Base
的析构函数,而不会调用 Derived
的析构函数。这是因为 Base
的析构函数没有被声明为 virtual
,导致多态行为失效。
5.Base::count
在析构完所有对象后为 0
。Derived::count
在析构完所有对象后为 13
,因为 Derived
的析构函数没有被调用。