class Base {
public:
int get_i() {
return m_i;
}
void set_i(int i) {
m_i = i;
}
private:int m_i;
};
int main()
{
Base b;
b.set_i(1);
cout << b.get_i() <<endl;
//cout << b.m_i <<endl;//compile error
//cannot access private member
}
class CParent
{
public:
CParent() {}//step2
virtual ~CParent() {}
public:
void Print() { std::cout << "1,"; }
};
class CSon : public CParent
{
public:
CSon() {}//step1 step4
virtual ~CSon() {}
public:
virtual void Print() { std::cout << "2,"; }
};
int main()
{
CParent * pParent = new CSon();
pParent->Print();
delete pParent;
return 0;
}
输出为1,
virtual只对自己以下的继承有效,对之上的继承无效。
类中调用自己的成员 虚函数。
class CParent
{
public:
CParent() {Print();}//step2
virtual ~CParent() {}
public:
virtual void Print()
{
std::cout << "1,";//step3
}
void print1() {Print();}//step2
};
class CSon : public CParent
{
public:
CSon() {Print();}//step1 step4
virtual ~CSon() {}
public:
void Print()
{
std::cout << "2,";//step5
}
void print1() {Print();}//step2
};
int main()
{
CParent * pParent = new CSon();//(对象)
pParent->print1();
delete pParent;
return 0;
}
以上结果输出为1,2,2
原因:继承关系中,构造调用顺序从基类到派生类,类调用本地版本,因为虚函数在构造中不起作用,为什么?原因很简单,构造过程中派生类的信息还没有存在,如果调用将非常危险
C++标准规定了在构造函数中调用虚函数时,只会绑定到自己类的相应函数,因为即使此时是一个子类的对象构造,但在执行父类的构造函数是,子类的变量还没有初始化,虚函数表可能都还没有构造好,所以,标准里禁止此时调用子类的虚函数。
class CParent
{
public:
CParent() {
Print();
}
virtual ~CParent() {}
public:
virtual void Print() = 0;
};
class CSon : public CParent
{
public:
CSon() {Print();}
virtual ~CSon() {}
public:
void Print()
{
std::cout << "2,";
};
};
int main() {
CParent *pParent = new CSon();
delete pParent;
}
这道题不能通过编译,与第上题类似,在构造函数里,不会进行动态绑定,即使是虚函数。而这时,基类的构造函数里调用Print是基类本身的,但Print没有实现,所以
编译器不能通过链接。若基类中去掉Print函数,则能编译成功
class Base
{
public:
virtual bool operator == (int iValue)
{
std::cout << "I am Base class !" << std::endl;
return true;
}
virtual ~Base(){}
};
class Derive: public Base
{
public:
virtual bool operator == (int iValue)
{
std::cout << "I am Derive class !" << std::endl;
return true;
}
virtual ~Derive(){}
};
int main()
{
Derive derive;
Base* pBase = &derive;
Derive* pDerive = &derive;
*pBase == 0;
*pDerive == 0;
return 0;
}
程序的输出结果是____:
I am Derive class !
I am Derive class !
操作符重载函数也是可以是虚函数的。
class Base
{
public:
virtual void display(std::string strShow = "Base default string!")
{
std::cout << strShow << std::endl;
std::cout <<"In Base"<< std::endl;
}
virtual ~Base(){}
};
class Derive: public Base
{
public:
virtual void display(std::string strShow = "Derive default string!")
{
std::cout << strShow << std::endl;
std::cout <<"In Derive"<< std::endl;
}
virtual ~Derive(){}
};
int main()
{ Base* pBase = new Derive(); Derive* pDerive = new Derive();
pBase->display();
pDerive->display();
delete pBase;
delete pDerive;
return 0;
}
I am Base class !
In Derive
I am Derive class !
In Derive
虚函数是动态绑定,但默认值是在编译期决定的。对pBase->display进行调用时,实际还是调用的Derive::display,但传入的默认参数却是参照Base::display的。
关于const修饰函数返回值的测试
class Base
{
public:
// if there is display(), then display()
// if there is no display(), then display() const
virtual void display()
{
std::cout << "I am Base class display!" << std::endl;
}
virtual void display() const
{
std::cout << "I am Base class display const!" << std::endl;
}
virtual int display1(const int i)
{
std::cout << "I am Base class display1!" << std::endl;
return 1;
}
//virtual int display1(int i)
//int display1(int i)
// class member cannot be redeclared
//const int display1(const int i)
//char display1(const int i)
// functions that differ only in return type cannot be overload
// const修饰返回值为值的时候没有意义,只有在修饰返回值为指针的时候才有意义。
// 返回值为值的时候,重新赋值之后约束不到对方。
// 返回值为指针的时候,重新赋值的时候强制对方也为const
const int display2()
{
int result = 1;
std::cout << "I am Base class display2!" << std::endl;
return result;
}
//指针必须为const
const char* display3()
{
char* result = new char(10);
memset(result, 0, 10);
result[0] = 'a';
result[1] = 0;
return result;
}
//没有意义,全依赖重新赋值时候的约束
char* const display4()
{
char* result = new char(10);
memset(result, 0, 10);
result[0] = 'b';
result[1] = 0;
return result;
}
virtual ~Base(){}
};
int main()
{
Base* pBase = new Base();
pBase->display();
pBase->display1(1);
int int1 = pBase->display2();
int1++;
std::cout << int1 <<endl;
//char* char1 = pBase->display3();
//char* const char1 = pBase->display3();
// Cannot initialize a variable of type 'char *' with an rvalue of type 'const char *'
const char* char1 = pBase->display3();
printf("%s\n", char1);
//char1[0] = 'c';
// readobly variable is not assaignable
const char* char2 = pBase->display4();
printf("%s\n", char2);
//char2[0] = 'c';
// readobly variable is not assaignable
char2 = new char(10);
char* const char3 = pBase->display4();
char3[0] = 'c';
printf("%s\n", char3);
//char3 = new char(10);
// cannot assign to variable 'char3' with const-qualified type 'char *const'
delete pBase;
return 0;
}
输出为:
I am Base class display!
I am Base class display1!
I am Base class display2!
2
a
b
c
class Base
{
public:
virtual void display() const
{
std::cout << "I am Base class !" << std::endl;
}
virtual int display1(const int i)
{
std::cout << "I am Base class !" << std::endl;
return 1;
}
virtual const int display2()
{
int result = 1;
std::cout << "I am Base class !" << std::endl;
return result;
}
virtual ~Base(){}
};
class Derive: public Base
{
public:
// if there are both const or not const the all derived function
virtual void display() //const
{
std::cout << "I am Derive class !"<< std::endl;
}
virtual int display1(int i)
{
std::cout << "I am Derive class !" << std::endl;
return 1;
}
virtual const int display2()
//virtual int display2()//compile failed
//virtaul function display2 have diferrent return type ('int') than
//the function it overrides (which has a return type 'const int)
{
int result = 1;
std::cout << "I am Derive class !" << std::endl;
return result;
}
virtual ~Derive(){}
};
int main()
{
Base* pBase = new Derive();
Derive* pDerive = new Derive();
pBase->display();
pDerive->display();
pBase->display1(1);
pDerive->display1(1);
delete pBase;
delete pDerive;
return 0;
}
I am Base class !
I am Derive class !
I am Derive class !
I am Derive class !
加了const以后,是两个不同的函数,Derive实际上有三个虚函数。如果基类virtual void display() const中的const去掉,则子类相当于重载了此基类函数,答案就是
I am Derive class !
I am Derive class !
首先要认识到这是两个不同的函数
其次,通过Base *p去调用display,这个display必须是基类声明的display,因为基类的指针不可能调用到派生类声明的方法,它根本不可能知道派生类有哪些方法,所以 pBase->display();只会调用基类的方法(如果派生类重写了,则根据多态会调用派生类的实现),这个地方不能把多态加进来,多态是运行期的概念,但编译的时候,pBase->display()就被绑定到display const这个方法了(不可能说因为pBase实际上是一个派生类的对象来进行绑定),由于派生类没有重载display const这个方法,输出为”I am base class !”
pDerive->display();调用因为pDerive不是const的,绑定到非const的方法,可试试把pDerive加上const修饰符,输出就会变的
"virtual void display() const"与"virtual void display()"是不同的两个接口,就如同"virtual void display_const()"与"virtual void display()"是两个接口一样。
因此在Derive中,实际上有个虚函数
"virtual void display() const"
"virtual void display()"
"virtual ~Derive()"
并且,"virtual void display() const"是从父类继承下来的,而且没有重写它。
因此pBase->display()虽然调用的是子类的"virtual void display() const"函数,但子类没有重写它,实际还是调用的父类的"virtual void display() const"函数。
而pDerive->display()则优先调用自己类的"virtual void display()"函数。
另外,对于const 修饰函数的三个位置的思考,
修饰函数返回值:如果基类和派生类不一致,会产生编译失败;
修饰入参:不影响,认为是一样的;
修饰函数本身,认为是不一样的。
const函数的使用
class Base
{
public:
void display()
{
std::cout << "I am display function!" << std::endl;
m_i = 0;
//m_j = 0;//compile failed
//cannnot assign to non-static data member 'm_j' with const-qualified type 'const int'
}
void display() const
{
std::cout << "I am display const function!" << std::endl;
//m_i = 0;//compile failed
//cannot assign to non-static data member within const member function display.
}
int display1(const int i)
{
std::cout << "I am display1 function!" << std::endl;
//i = 2;//compile failed
//cannot assign to variable "i" with consit -qualified type 'const int'
return 1;
}
const int display2()
{
int result = 1;
std::cout << "I am display1 function!" << std::endl;
return result;
}
//void display2(){}//compile failed
//int display2(){}//compile failed
//functions that differ only in their return type cannot be overloaed
void display3() const
{
std::cout << "I am display3 const function!" << std::endl;
//m_i = 0;//compile failed
//cannot assign to non-static data member within const member function display.
}
~Base(){}
private:
int m_i;
//const int m_j;//compile failed
//when instantialize, canll to implicitlly default constaructor of 'Base'
const int m_j = 0;
};
int main()
{
//*
Base* pBase = new Base();
const Base* cBase = new Base();
pBase->display();
cBase->display();
pBase->display1(1);
//cBase->display1(1);//compile failed
//this argument to member function displayq has type 'const base' but function is not marked const
pBase->display3();
cBase->display3();
delete pBase;
delete cBase;
//*/
return 0;
}
https://www.cnblogs.com/2018shawn/p/10853607.html
1.const 修饰类的成员变量,表示成员常量,不能被修改。
2.const修饰函数承诺在本函数内部不会修改类内的数据成员,不会调用其它非 const 成员函数。
3.如果 const 构成函数重载,const 对象只能调用 const 函数,非 const 对象优先调用非 const 函数(没有非const函数则调用const函数)。
4.const 函数只能调用 const 函数。非 const 函数可以调用 const 函数。
5.类体外定义的 const 成员函数,在定义和声明处都需要 const 修饰符
6.const在*的左边,则指针指向的变量的值,不可直接通过指针改变(可以通过其他途径改变);
在*的右边,则指针的指向不可变。简记为“左定值,右定向”。
class A
{
public:
void Func() {} // 如果没有{}, 则无法解析外部命令
void Func2() {cout<<"A::Func2"<<endl;};
};
class B
{
private:
bool Func() const {}
bool Func2() const {;};
};
class C:
public A,
public B
{
}; // class definition is unimportant
int main()
{
C test;
//test.Func(); //look here
//Member 'Func' found in multiple base classes of different types
//member found by ambiguous name lookup
}
A.test.B::Func(); B.test.A::Func();
C.B::test.Func(); D.A::test.Func();
考察多重继承的问题,B的Func函数是私有的,所以A不能正确访问。
对于下面的代码,描述正确的是:
class A
{
public:
virtual void test();
};
class B: public A
{
public:
void test();
//...
};
class C: public B
{
public:
void test();
//...
};
A.B类的test函数是虚函数,而C类的也是
B.B类的test函数不是虚函数
C.B类的test函数是虚函数,而C类的不是
D.C类的test函数不是虚函数
基本概念。如果父类里声明了某函数为虚函数,则在子类此函数的声明里不管有没有"vitrual"关键子,都是虚函数。即使访问权限发生变化。如C声明为:
class C: public B
{
private:
void test();
...
};
则test一样是虚函数。
以下程序的输出是:
class Base
{
public:
int a = 0;
Base() { std::cout << __FUNCTION__ << std::endl; }
virtual ~Base() { std::cout << __FUNCTION__ << std::endl; }
virtual void print() { std::cout << __FUNCTION__ << " " << a << std::endl; }
};
class Derive1:public Base
{
public:
int a = 1;
int d1 = 10;
Derive1() { std::cout << __FUNCTION__ << std::endl; }
~Derive1() { std::cout << __FUNCTION__ << std::endl; }
virtual void print1() { std::cout << __FUNCTION__ << " " << a << std::endl; }
};
class Derive2 : public Derive1
{
public:
int a = 2;
int d2 = 20;
Derive2() {std::cout << __FUNCTION__ << std::endl; }
~Derive2() {std::cout << __FUNCTION__ << std::endl; }
virtual void print2() { std::cout << __FUNCTION__ << " " << a << std::endl; }
};
int main()
{
/*
Derive1* p1 = new Derive2();
p1->print();
((Derive1*)p1)->print1();
((Derive2*)p1)->print2();
//*/
/*
Derive2 d2;
Derive1& p1 = d2;
cout << p1.a << p1.Base::a;
Derive2 d3;
Derive1* p2 = &d3;
cout << p2->a << p2->Base::a << ((Derive2*)p2)->Derive2::a;
//*/
Derive1* pObj = new Derive2();
delete pObj;
return 0;
}
Base::Base
Derive1::Derive1
Derive2::Derive2
Derive2::~Derive2
Derive1::~Derive1
Base::~Base