A 派生类一般都用公有派生
B 对基类成员的访问必须是无二义性的
C 赋值兼容规则也适用于多重继承的组合
D 父类的公有成员在派生类中仍然是公有的
正确答案:D
赋值兼容规则:
1.子类对象可以直接赋值给父类对象
2.子类对象的地址可以直接赋值给父类对象
3.子类的对象可以对父类对象的引用初始化
class Base
{};
class D : public Base
{};
void main()
{
Base b;
D d;
//1
b = d;
//2
Base *pb = &d;
//3
Base &rb = d;
}
#include
using namespace std;
class parent {
int i;
protected:
int x;
public:
parent()
{ x = 0; i = 0; }
void change()
{ x++; i++; }
void display();
};
class son :public parent {
public:
void modify();
};
void parent::display() {
cout << "x=" << x << endl;
}
v
oid son::modify() {
x++;
}
i
nt main() {
son A;
parent B;
A.display();
A.change();
A.modify();
A.display();
B.change();
B.display();
return 0;
}
A x=1
x=0
x=2
B x=2
x=0
x=1
C x=0
x=2
x=1
D x=0
x=1
x=2
正
确答案:C
A,B是两个不同的对象,有自己不同的空间地址
自己改变自己的
A 派生类的虚函数与基类的虚函数具有不同的参数个数和类型
B 内联函数不能是虚函数
C 派生类必须重新定义基类的虚函数
D 虚函数可以是一个static型的函数
正确答案:B
虚函数重写:三同!
inline是关键字只是一种建议,内联函数要被展开,没有地址。虚表是需要地址的。
可以不构成多态就不用重新定义
A 如果派生类没有定义析构函数,则只调用基类的析构函数
B 如果基类没有定义析构函数,则只调用派生类的析构函数
C 先调用派生类的析构函数,后调用基类的析构函数
D 先调用基类的析构函数,后调用派生类的析构函数
正确答案:C
有默认的析构函数,有没有定义都得调
先调用父类的构造函数,再调用子类的构造函数
先调用子类的析构函数,再调用父类的析构函数
A 声明纯虚函数的类不能实例化
B 声明纯虚函数的类成虚基类
C 子类必须实现基类的
D 纯虚函数必须是空函数
正确答案:A
虚基类是避免菱形继承双份的方法,与纯虚函数没有关系
1)const char *p,这是一个常量指针,p的值不可修改
2)在64位机上,char *p= “abcdefghijk”; sizeof§大小为12
3)inline会检查函数参数,所以调用开销显著大于宏
4)重载是编译时确定的,虚函数是运行时绑定的
A 1
B 2
C 3
D 4
正确答案:A
常量指针:所指框架的值是一个常量,不能改变指针的指向
指针常量:不能改变指针的指向,但是可以指针解引用改变所指空间的值
区分:const在的左边是常量指针 const在的右边是指针常量
这里是指针常量
指针的大小就是8个字节,64位
宏和内联都会被展开,运行时的效率没有太大区别
A 释放父类指针时能正确释放子类对象
B 释放子类指针时能正确释放父类对象
C 这样做是错误的
D 以上全错
正确答案:A
子类里面已经完整的包含了一个父类
析构的时候只看类型——这里就只会调用父类析构函数
会造成资源的泄漏
定义成虚函数之后,形成一种多态,释放的时候就会自动去调用子类的析构函数
void main()
{
Base *pb = new D;
delete pb;
}
A 多态性是指同名函数对应多种不同的实现
B 重载方式仅有函数重载
C 重载方式包含函数重载和运算符重载
D 多态性表现为静态和动态两种方式
正确答案:B
还有运算符重载
静态——重载
动态——运行时决议
#include
using namespace std;
class B
{
public:
B()
{
cout << "default constructor" << " ";
}
~
B()
{
cout << "destructed" << " ";
}
B
(int i): data(i)
{
cout << "constructed by parameter" << data << " ";
}
p
rivate: int data;
};
B Play( B b)
{
return b;
}
i
nt main(int argc, char *argv[])
{
B temp = Play(5);//先构造出一个B(5)——调动一次构造方法 拷贝构造
return 0;
}
A constructed by parameter5 destructed destructed
B constructed by parameter5 destructed
C default constructor" constructed by parameter5 destructed
D default constructor" constructed by parameter5 destructed destructed
正确答案:A
调动一次有参的构造方法和两次次析构方法
会产生一个临时的对象,拷贝构造给B
但会存在编译器的优化
#include
using namespace std;
class A
{
p
ublic:
virtual void print()
{
cout << "A::print()" << "\n";
}
};
class B: public A
{ p
ublic: virtual void print()
{
cout << "B::print()" << "\n";
}
};
class C: public A
{ p
ublic: virtual void print()
{
cout << "C::print()" << "\n";
}
};
void print(A a)
{
a.print();
}
i
nt main()
{
A a, *aa, *ab, *ac;
B b;
C c;
aa = &a;
ab = &b;
ac = &c;
a.print();
b.print();
c.print();
aa->print();
ab->print();
ac->print();
print(a);
print(b);
print(c);
}
A C::print() B::print() A::print() A::print() B::print() C::print() A::print() A::print() A::print()
B A::print() B::print() C::print() A::print() B::print() C::print() A::print() A::print() A::print()
C A::print() B::print() C::print() A::print() B::print() C::print() B::print() B::print() B::print()
D C::print() B::print() A::print() A::print() B::print() C::print() C::print() C::print() C::print()
正确答案:B
通过对象访问——静态绑定
父类指针访问——多态
通过父类对象去访问,无论是哪一个子类对象,调用的都是父类的方法——不是多态
在命令行输入如下命令:
xcopy /s c:\ d:\e,
各个参数如下:
参数1:命令字xcopy
参数2:字符串/s
参数3:字符串c:\
参数4: 字符串d:\e
请编写一个参数解析程序,实现将命令行各个参数解析出来。
解析规则:
1.参数分隔符为空格
2.对于用""包含起来的参数,如果中间有空格,不能解析为多个参数。比如在命令行输入xcopy /s
“C:\program files” "d:“时,参数仍然是4个,第3个参数应该是字符串C:\program files,而不是
C:\program,注意输出参数时,需要将”"去掉,引号不存在嵌套情况。
3.参数不定长
4.输入由用例保证,不会出现不符合要求的输入
输入描述:
输入一行字符串,可以有空格
输出描述:
输出参数个数,分解后的参数,每个参数都独占一行
示例1:
输入
xcopy /s c:\ d:\e
输出
4 x
copy
/s
c:\
d:\e
正确答案:
#include
#include
#include
using namespace std;
void cmdLine(const string &str)
{
string tmp = "";
int flag = false;//标记是否是字符串
vector<string> cur;//cur是一个以string为单位的向量
for(int i = 0;i<str.size();i++)
{
if(str[i] == '"')
{
flag = !flag;//变成true就是证明是字符串里的,空格就不作为分隔符
}
else if(str[i] == ' ' && !flag)//不是字符串里的空格,才是分隔符
{
cur.push_back(tmp);//遇到空格就将之前保存在tmp的内容尾插到cur中
tmp = "";//置空,再次以空字符串进行下一个判断
}
else//没有遇到空格就加等到另外一个字符串中
{
tmp += str[i];
}
}
cur.push_back(tmp);//将最后一个字符串尾插到cur中,因为最后一个后没有空格
cout<<cur.size()<<endl;
for(int i = 0;i<cur.size();i++)
{
cout<<cur[i]<<endl;
}
}
int main() {
string str;
while(getline(cin,str))
{
cmdLine(str);
}
return 0;
}
小易来到了一条石板路前,每块石板上从1挨着编号为:1、2、3…
这条石板路要根据特殊的规则才能前进:对于小易当前所在的编号为K的 石板,小易单次只能往前跳K的一个
约数(不含1和K)步,即跳到K+X(X为K的一个非1和本身的约数)的位置。 小易当前处在编号为N的石板,他想
跳到编号恰好为M的石板去,小易想知道最少需要跳跃几次可以到达。
例如:
N = 4,M = 24:
4->6->8->12->18->24
于是小易最少需要跳跃5次,就可以从4号石板跳到24号石板
输入描述:
输入为一行,有两个整数N,M,以空格隔开。 (4 ≤ N ≤ 100000) (N ≤ M ≤ 100000)
输出描述:
输出小易最少需要跳跃的步数,如果不能到达输出-1
示例1:
输入
4 24
输出
5
正确答案:
#include
#include
#include
#include
using namespace std;
void get_div(int v,vector<int> &a)
{
for(int i = 2;i<=sqrt(v);i++)//开方要包头文件
{
if(v%i == 0)
{
a.push_back(i);
//将开方的一半传过去
if(v/i != i)
a.push_back(v/i);
}
}
}
int Jump(int n,int m)
{
vector<int> step(m+1,INT_MAX);//INT_MAX表示不可以达到,要包含头文件,m+1多开一个空间的位置
step[n] = 0;//初始化其实位置,一开始站的位置是n,表示第0步
//从n开始跳到m的位置
for(int i = n;i<m;i++)
{
//如果n是不可到达的位置就结束
if(step[i] == INT_MAX)
continue;
vector<int> a;
get_div(i,a);//获取i的约数,并保存到a中
//计算步数
for(int j = 0; j<a.size();j++)
{
if(a[j]+i<=m && step[a[j]+i] != INT_MAX)
{
//需要挑选一个最小值
step[a[j]+i] = step[a[j]+i] < step[i]+1 ? step[a[j]+i] : step[i]+1;
}
else if(a[j] + i <= m)
{
step[a[j]+i] = step[i] + 1;
}
}
}
return step[m] == INT_MAX ? -1 : step[m];
}
int main() {
int n,m,min_step;
while(cin>>n>>m)
{
min_step = Jump(n,m);
cout<<min_step<<endl;
}
return 0;
}