为什么我们需要C++;? 我正在学习C++,我正在学习虚拟函数。< /P>
从我所读到的(在书中和网上),虚函数是基类中的函数,可以在派生类中重写 但在本书的早些时候,在学习基本继承时,我能够在派生类中重写基函数,而无需使用为什么我们需要C++;? 我正在学习C++,我正在学习虚拟函数。< /P>,c++,virtual-functions,C++,Virtual Functions,从我所读到的(在书中和网上),虚函数是基类中的函数,可以在派生类中重写 但在本书的早些时候,在学习基本继承时,我能够在派生类中重写基函数,而无需使用virtual 那么我在这里错过了什么?我知道虚拟函数还有很多,它似乎很重要,所以我想弄清楚它到底是什么。我只是在网上找不到一个直截了当的答案。您至少需要一个继承级别和一个向上转换来演示它。下面是一个非常简单的例子: class Animal { public: // turn the following vir
virtual
那么我在这里错过了什么?我知道虚拟函数还有很多,它似乎很重要,所以我想弄清楚它到底是什么。我只是在网上找不到一个直截了当的答案。您至少需要一个继承级别和一个向上转换来演示它。下面是一个非常简单的例子:
class Animal
{
public:
// turn the following virtual modifier on/off to see what happens
//virtual
std::string Says() { return "?"; }
};
class Dog: public Animal
{
public: std::string Says() { return "Woof"; }
};
void test()
{
Dog* d = new Dog();
Animal* a = d; // refer to Dog instance with Animal pointer
std::cout << d->Says(); // always Woof
std::cout << a->Says(); // Woof or ?, depends on virtual
}
类动物
{
公众:
//打开/关闭以下虚拟修改器以查看发生了什么
//虚拟的
std::string说(){return“”;}
};
犬类:公共动物
{
public:std::string Says(){return“Woof”;}
};
无效测试()
{
狗*d=新狗();
Animal*a=d;//使用Animal指针引用Dog实例
std::cout Says();//始终汪汪
std::cout Says();//Woof or?,取决于虚拟
}
您必须区分重写和重载。如果没有virtual
关键字,您只能重载基类的方法。这只意味着隐藏。
假设您有一个基类base
和一个派生类Specialized
,它们都实现了void foo()
。现在,您有一个指向Base
的指针,指向专用
的实例。当您在其上调用foo()
时,您可以观察到virtual
的不同之处:如果该方法是虚拟的,则将使用专用的
实现,如果缺少,则将选择Base
中的版本。
最好不要重载基类中的方法。将方法设置为非虚拟是其作者告诉您它在子类中的扩展不是有意的。如果基类是
base
,而派生类是Der
,则可以使用base*p
指针实际指向Der
的实例。当您调用p->foo()时
,如果foo
不是虚拟的,则执行Base
的版本,忽略p
实际指向Der
的事实。如果foo是虚拟的,p->foo()
执行对foo
的“最叶”覆盖,充分考虑所指向项的实际类。因此,虚拟和非虚拟之间的区别实际上非常关键:前者允许运行时,这是面向对象编程的核心概念,而后者则不允许。如果没有“虚拟”,您将获得“早期绑定”。该方法的哪个实现在编译时根据您调用的指针类型决定
使用“虚拟”,您将获得“后期绑定”。该方法的哪个实现在运行时根据指向对象的类型(它最初的构造形式)确定。这不一定是您根据指向该对象的指针类型所想的
class Base
{
public:
void Method1 () { std::cout << "Base::Method1" << std::endl; }
virtual void Method2 () { std::cout << "Base::Method2" << std::endl; }
};
class Derived : public Base
{
public:
void Method1 () { std::cout << "Derived::Method1" << std::endl; }
void Method2 () { std::cout << "Derived::Method2" << std::endl; }
};
Base* obj = new Derived ();
// Note - constructed as Derived, but pointer stored as Base*
obj->Method1 (); // Prints "Base::Method1"
obj->Method2 (); // Prints "Derived::Method2"
类基
{
公众:
void Method1(){std::cout以下是我如何理解函数的含义,以及为什么需要这些函数:
假设您有以下两个类:
class Animal
{
public:
void eat() { std::cout << "I'm eating generic food."; }
};
class Cat : public Animal
{
public:
void eat() { std::cout << "I'm eating a rat."; }
};
到目前为止还不错,对吧?动物吃普通食物,猫吃老鼠,都没有virtual
现在让我们稍微修改一下,以便通过中间函数调用eat()
现在我们的主要功能是:
Animal *animal = new Animal;
Cat *cat = new Cat;
func(animal); // Outputs: "I'm eating generic food."
func(cat); // Outputs: "I'm eating generic food."
哦……我们把一只猫传给了func()
,但它不会吃老鼠。如果你超负荷func()
,那么需要一只Cat*
?如果你必须从动物身上衍生出更多的动物,它们都需要自己的func()
解决方案是使用Animal
a类虚拟函数制作eat()
:
Animal *animal = new Animal;
Cat *cat = new Cat;
animal->eat(); // Outputs: "I'm eating generic food."
cat->eat(); // Outputs: "I'm eating a rat."
class Animal
{
public:
virtual void eat() { std::cout << "I'm eating generic food."; }
};
class Cat : public Animal
{
public:
void eat() { std::cout << "I'm eating a rat."; }
};
#include<iostream>
using namespace std;
class A{
public:
virtual void show(){
cout << " Hello from Class A";
}
};
class B :public A{
public:
virtual void show(){
cout << " Hello from Class B";
}
};
int main(){
A *a1 = new B;
a1->show();
}
#include <iostream>
using namespace std;
class father
{
public:
virtual void get_age() {cout << "Fathers age is 50 years" << endl;}
};
class son: public father
{
public : void get_age() { cout << "son`s age is 26 years" << endl;}
};
int main(){
father *p_father = new father;
son *p_son = new son;
p_father->get_age();
p_father = p_son;
p_father->get_age();
p_son->get_age();
return 0;
}
完成。当您在基类中有一个函数时,您可以在派生类中重新定义它或重写它
重新定义方法:
在派生类中给出了基类方法的新实现。不促进动态绑定
重写方法:
重新定义派生类中基类的虚拟方法。虚拟方法有助于动态绑定
所以当你说:
但在本书的早些时候,当我学习基本的继承时
能够重写派生类中的基方法,而无需使用
“虚拟的”
你没有重写它,因为基类中的方法不是虚拟的,而是重新定义它
它帮助你知道底层机制。C++将C程序员使用的一些编码技术正式化,“类”用“覆盖”替换。-具有公共标题部分的结构将用于处理不同类型的对象,但具有一些公共数据或操作。通常是覆盖的基本结构(公共部分)有一个指向函数表的指针,它指向每个对象类型的不同例程集合。C++做同样的事情,但是隐藏了C++、<代码> PTR > FUNC(…)代码>的机制,其中FUNC是虚拟的,如C将是代码>(*PTR >函数表[FooSnNuM])(PTR,…)
,其中派生类之间更改的是func_表内容。[非虚拟方法ptr->func()只是转换为mangled_func(ptr,…)]
这样做的结果是,为了调用派生类的方法,您只需要理解基类,也就是说,如果例程理解类a,您可以向它传递一个派生类B指针,那么调用的虚拟方法将是派生类B的方法
#include <iostream>
using namespace std;
class Expression
{
public:
auto value() const
-> double
{ return 0.0; } // This should never be invoked, really.
};
class Number
: public Expression
{
private:
double number_;
public:
auto value() const
-> double
{ return number_; } // This is OK.
Number( double const number )
: Expression()
, number_( number )
{}
};
class Sum
: public Expression
{
private:
Expression const* a_;
Expression const* b_;
public:
auto value() const
-> double
{ return a_->value() + b_->value(); } // Uhm, bad! Very bad!
Sum( Expression const* const a, Expression const* const b )
: Expression()
, a_( a )
, b_( b )
{}
};
auto main() -> int
{
Number const a( 3.14 );
Number const b( 2.72 );
Number const c( 1.0 );
Sum const sum_ab( &a, &b );
Sum const sum( &sum_ab, &c );
cout << sum.value() << endl;
}
#include <iostream>
using namespace std;
class Expression
{
public:
virtual
auto value() const -> double
= 0;
};
class Number
: public Expression
{
private:
double number_;
public:
auto value() const -> double
override
{ return number_; }
Number( double const number )
: Expression()
, number_( number )
{}
};
class Sum
: public Expression
{
private:
Expression const* a_;
Expression const* b_;
public:
auto value() const -> double
override
{ return a_->value() + b_->value(); } // Dynamic binding, OK!
Sum( Expression const* const a, Expression const* const b )
: Expression()
, a_( a )
, b_( b )
{}
};
auto main() -> int
{
Number const a( 3.14 );
Number const b( 2.72 );
Number const c( 1.0 );
Sum const sum_ab( &a, &b );
Sum const sum( &sum_ab, &c );
cout << sum.value() << endl;
}
#include <iostream>
using namespace std;
class Expression
{
protected:
typedef auto Value_func( Expression const* ) -> double;
Value_func* value_func_;
public:
auto value() const
-> double
{ return value_func_( this ); }
Expression(): value_func_( nullptr ) {} // Like a pure virtual.
};
class Number
: public Expression
{
private:
double number_;
static
auto specific_value_func( Expression const* expr )
-> double
{ return static_cast<Number const*>( expr )->number_; }
public:
Number( double const number )
: Expression()
, number_( number )
{ value_func_ = &Number::specific_value_func; }
};
class Sum
: public Expression
{
private:
Expression const* a_;
Expression const* b_;
static
auto specific_value_func( Expression const* expr )
-> double
{
auto const p_self = static_cast<Sum const*>( expr );
return p_self->a_->value() + p_self->b_->value();
}
public:
Sum( Expression const* const a, Expression const* const b )
: Expression()
, a_( a )
, b_( b )
{ value_func_ = &Sum::specific_value_func; }
};
auto main() -> int
{
Number const a( 3.14 );
Number const b( 2.72 );
Number const c( 1.0 );
Sum const sum_ab( &a, &b );
Sum const sum( &sum_ab, &c );
cout << sum.value() << endl;
}
#include<iostream>
using namespace std;
class A{
public:
void show(){
cout << " Hello from Class A";
}
};
class B :public A{
public:
void show(){
cout << " Hello from Class B";
}
};
int main(){
A *a1 = new B; // Create a base class pointer and assign address of derived object.
a1->show();
}
Hello from Class A.
#include<iostream>
using namespace std;
class A{
public:
virtual void show(){
cout << " Hello from Class A";
}
};
class B :public A{
public:
virtual void show(){
cout << " Hello from Class B";
}
};
int main(){
A *a1 = new B;
a1->show();
}
Hello from Class B.
interface IUnknown {
virtual HRESULT QueryInterface (REFIID riid, void **ppvObject) = 0;
virtual ULONG AddRef () = 0;
virtual ULONG Release () = 0;
};
class Base
{
virtual void func();
}
class Derive : public Base
{
void func();
}
class Animal {
public:
~Animal() {
cout << "Deleting an Animal" << endl;
}
};
class Cat:public Animal {
public:
~Cat() {
cout << "Deleting an Animal name Cat" << endl;
}
};
int main() {
Animal *a = new Cat();
delete a;
return 0;
}
Deleting an Animal
class Animal {
public:
virtual ~Animal() {
cout << "Deleting an Animal" << endl;
}
};
class Cat:public Animal {
public:
~Cat(){
cout << "Deleting an Animal name Cat" << endl;
}
};
int main() {
Animal *a = new Cat();
delete a;
return 0;
}
Deleting an Animal name Cat
Deleting an Animal
Shape *shape = new Triangle();
cout << shape->getName();
#include <iostream>
using namespace std;
class father
{
public: void get_age() {cout << "Fathers age is 50 years" << endl;}
};
class son: public father
{
public : void get_age() { cout << "son`s age is 26 years" << endl;}
};
int main(){
father *p_father = new father;
son *p_son = new son;
p_father->get_age();
p_father = p_son;
p_father->get_age();
p_son->get_age();
return 0;
}
Fathers age is 50 years
Fathers age is 50 years
son`s age is 26 years
#include <iostream>
using namespace std;
class father
{
public:
virtual void get_age() {cout << "Fathers age is 50 years" << endl;}
};
class son: public father
{
public : void get_age() { cout << "son`s age is 26 years" << endl;}
};
int main(){
father *p_father = new father;
son *p_son = new son;
p_father->get_age();
p_father = p_son;
p_father->get_age();
p_son->get_age();
return 0;
}
Fathers age is 50 years
son`s age is 26 years
son`s age is 26 years
Parent* p1 = &boy;
p1 -> task();
Parent* p2 = &girl;
p2 -> task();
Boy* p1 = &boy;
p1 -> task();
Girl* p2 = &girl;
p2 -> task();
Parent* p1 = &boy;
p1 -> task();
p1 = &girl;
p1 -> task();
double totalMonthBenefit = 0;
std::vector<CentralShop*> mainShop = { &shop1, &shop2, &shop3, &shop4, &shop5, &shop6};
for(CentralShop* x : mainShop){
totalMonthBenefit += x -> getMonthBenefit();
}
double totalMonthBenefit=0;
Shop1* branch1 = &shop1;
Shop2* branch2 = &shop2;
Shop3* branch3 = &shop3;
Shop4* branch4 = &shop4;
Shop5* branch5 = &shop5;
Shop6* branch6 = &shop6;
totalMonthBenefit += branch1 -> getMonthBenefit();
totalMonthBenefit += branch2 -> getMonthBenefit();
totalMonthBenefit += branch3 -> getMonthBenefit();
totalMonthBenefit += branch4 -> getMonthBenefit();
totalMonthBenefit += branch5 -> getMonthBenefit();
totalMonthBenefit += branch6 -> getMonthBenefit();
#include <iostream>
using namespace std;
class Basic
{
public:
virtual void Test1()
{
cout << "Test1 from Basic." << endl;
}
virtual ~Basic(){};
};
class VariantA : public Basic
{
public:
void Test1()
{
cout << "Test1 from VariantA." << endl;
}
};
class VariantB : public Basic
{
public:
void Test1()
{
cout << "Test1 from VariantB." << endl;
}
};
int main()
{
Basic *object;
VariantA *vobjectA = new VariantA();
VariantB *vobjectB = new VariantB();
object=(Basic *) vobjectA;
object->Test1();
object=(Basic *) vobjectB;
object->Test1();
delete vobjectA;
delete vobjectB;
return 0;
}
class Base { virtual void foo(); };
class Derived : Base
{
void foo(); // this is overriding Base::foo
};
#include <iostream>
#include <string>
using namespace std;
class Animal
{
public:
#ifdef VIRTUAL
virtual string says() { return "??"; }
#else
string says() { return "??"; }
#endif
};
class Dog: public Animal
{
public:
string says() { return "woof"; }
};
string func(Animal *a)
{
return a->says();
}
int main()
{
Animal *a = new Animal();
Dog *d = new Dog();
Animal *ad = d;
cout << "Animal a says\t\t" << a->says() << endl;
cout << "Dog d says\t\t" << d->says() << endl;
cout << "Animal dog ad says\t" << ad->says() << endl;
cout << "func(a) :\t\t" << func(a) << endl;
cout << "func(d) :\t\t" << func(d) << endl;
cout << "func(ad):\t\t" << func(ad)<< endl;
}
$ g++ virtual.cpp -o virtual
$ ./virtual
Animal a says ??
Dog d says woof
Animal dog ad says ??
func(a) : ??
func(d) : ??
func(ad): ??
$ g++ virtual.cpp -D VIRTUAL -o virtual
$ ./virtual
Animal a says ??
Dog d says woof
Animal dog ad says woof
func(a) : ??
func(d) : woof
func(ad): woof
class Animal:
def says(self):
return "??"
class Dog(Animal):
def says(self):
return "woof"
def func(a):
return a.says()
if __name__ == "__main__":
a = Animal()
d = Dog()
ad = d # dynamic typing by assignment
print("Animal a says\t\t{}".format(a.says()))
print("Dog d says\t\t{}".format(d.says()))
print("Animal dog ad says\t{}".format(ad.says()))
print("func(a) :\t\t{}".format(func(a)))
print("func(d) :\t\t{}".format(func(d)))
print("func(ad):\t\t{}".format(func(ad)))
Animal a says ??
Dog d says woof
Animal dog ad says woof
func(a) : ??
func(d) : woof
func(ad): woof
#include <iostream>
using namespace std;
class Animal {
public:
virtual void MakeTypicalNoise() = 0; // no implementation needed, for abstract classes
virtual ~Animal(){};
};
class Cat : public Animal {
public:
virtual void MakeTypicalNoise()
{
cout << "Meow!" << endl;
}
};
class Dog : public Animal {
public:
virtual void MakeTypicalNoise() { // needs to be virtual, if subtype polymorphism is also needed for Dogs
cout << "Woof!" << endl;
}
};
class Doberman : public Dog {
public:
virtual void MakeTypicalNoise() {
cout << "Woo, woo, woow!";
cout << " ... ";
Dog::MakeTypicalNoise();
}
};
int main() {
Animal* apObject[] = { new Cat(), new Dog(), new Doberman() };
const int cnAnimals = sizeof(apObject)/sizeof(Animal*);
for ( int i = 0; i < cnAnimals; i++ ) {
apObject[i]->MakeTypicalNoise();
}
for ( int i = 0; i < cnAnimals; i++ ) {
delete apObject[i];
}
return 0;
}
Meow!
Woof!
Woo, woo, woow! ... Woof!
class base {
public:
void helloWorld() { std::cout << "Hello World!"; }
};
class derived: public base {
public:
void helloWorld() { std::cout << "Greetings World!"; }
};
int main () {
base hwOne;
derived hwTwo = new derived();
base->helloWorld(); //prints "Hello World!"
derived->helloWorld(); //prints "Hello World!"
#include <iostream>
using namespace std;
class base {
public:
void helloWorld() { std::cout << "Hello World!"; }
};
class derived : public base {
public:
void displayHWDerived(void(derived::*hwbase)()) { (this->*hwbase)(); }
void(derived::*hwBase)();
void helloWorld() { std::cout << "Greetings World!"; }
};
int main()
{
base* b = new base(); //Create base object
b->helloWorld(); // Hello World!
void(derived::*hwBase)() = &derived::helloWorld; //create derived member
function pointer to base function
derived* d = new derived(); //Create derived object.
d->displayHWDerived(hwBase); //Greetings World!
char ch;
cin >> ch;
}
#include "iostream"
//This class is created by Gun1's company
class Gun1 {public: void fire() {std::cout<<"gun1 firing now\n";}};
//This class is created by Gun2's company
class Gun2 {public: void shoot() {std::cout<<"gun2 shooting now\n";}};
//We create an abstract class to interface with WeaponController
class WeaponsInterface {
public:
virtual void shootTarget() = 0;
};
//A wrapper class to encapsulate Gun1's shooting function
class WeaponGun1 : public WeaponsInterface {
private:
Gun1* g;
public:
WeaponGun1(): g(new Gun1()) {}
~WeaponGun1() { delete g;}
virtual void shootTarget() { g->fire(); }
};
//A wrapper class to encapsulate Gun2's shooting function
class WeaponGun2 : public WeaponsInterface {
private:
Gun2* g;
public:
WeaponGun2(): g(new Gun2()) {}
~WeaponGun2() { delete g;}
virtual void shootTarget() { g->shoot(); }
};
class WeaponController {
private:
WeaponsInterface* w;
WeaponGun1* g1;
WeaponGun2* g2;
public:
WeaponController() {g1 = new WeaponGun1(); g2 = new WeaponGun2(); w = g1;}
~WeaponController() {delete g1; delete g2;}
void shootTarget() { w->shootTarget();}
void changeGunTo(int gunNumber) {//Virtual functions makes it easy to change guns dynamically
switch(gunNumber) {
case 1: w = g1; break;
case 2: w = g2; break;
}
}
};
class BattlefieldSoftware {
private:
WeaponController* wc;
public:
BattlefieldSoftware() : wc(new WeaponController()) {}
~BattlefieldSoftware() { delete wc; }
void shootTarget() { wc->shootTarget(); }
void changeGunTo(int gunNumber) {wc->changeGunTo(gunNumber); }
};
int main() {
BattlefieldSoftware* bf = new BattlefieldSoftware();
bf->shootTarget();
for(int i = 2; i > 0; i--) {
bf->changeGunTo(i);
bf->shootTarget();
}
delete bf;
}