C++ 抽象类的好处是什么
举个例子,C++ 抽象类的好处是什么,c++,abstract-class,C++,Abstract Class,举个例子, class base{ public: virtual void abstract() = 0; }; class derived:public base{ public: void abstract(){cout << "Abstract\n";} }; int main{ derived d; d.abstract(); return 0; } 类基{ 公众: 虚空抽象()=0; }; 派生类:公共基{ 公众: void abstract(){cout抽象类用于
class base{
public:
virtual void abstract() = 0;
};
class derived:public base{
public:
void abstract(){cout << "Abstract\n";}
};
int main{
derived d;
d.abstract();
return 0;
}
类基{
公众:
虚空抽象()=0;
};
派生类:公共基{
公众:
void abstract(){cout抽象类用于为某些功能提供接口,其中确切的行为由调用方的类定义。为了确保函数的“用户”实现其功能,您可以在基类中使用抽象函数。这样,如果“用户”没有提供所需的函数之一,代码无法编译。正如您所注意到的,在示例代码中,没有必要使用单独的基类和派生类
通常,具有虚拟函数的类的用途是动态多态性,但您的代码没有使用它
假设您有一些代码使用了base*
,而不知道它实际指向(几个)派生类中的哪一个。假设它们各自有abstract()的不同实现
。假设您想强制编写base
派生类的任何人实现自己版本的abstract()
。那么有理由将abstract()
设为纯虚拟函数,从而有理由将base
设为抽象类:
#include <iostream>
#include <cstdlib>
#include <ctime>
struct Base {
virtual void abstract() = 0;
virtual ~Base() {};
};
struct Derived1 : Base {
void abstract() { std::cout << "Derived1\n"; }
};
struct Derived2 : Base {
void abstract() { std::cout << "Derived2\n"; }
};
Base *random_object() {
if (std::rand() < RAND_MAX/2) {
return new Derived1();
} else {
return new Derived2();
}
}
int main() {
std::srand(std::time(0));
Base *b = random_object();
b->abstract();
delete b;
}
#包括
#包括
#包括
结构基{
虚空抽象()=0;
虚~Base(){};
};
结构Derived1:Base{
void abstract(){std::cout一个抽象(基)类的目的是为子类定义一个接口
。通过这种方式,你可以确定你的类必须能够做什么(它的方法),而不是它如何做事情(实现)。
当您从抽象类派生时,您承诺在子类中提供特定行为。使用此方法,函数可以使用您的对象并执行其操作,而无需详细了解其特定行为。
到处都有类层次结构,如.NET
-framework中的类层次结构,用于表示诸如UI控件之类的概念或事物。
第二,有一个类的实例有时是没有意义的。考虑一个类<代码>动物< /代码>。<代码>动物< /代码>是如何定义的?实例化一个<代码>动物< /代码>是没有意义的,而是一个<代码>狗< /代码>或一个<代码>猫>代码>,源于<代码>动物。< /代码> 在“抽象”字,抽象类中。(完全抽象时也称为接口)从一组类似类的实现中抽象出来。在这里,相似意味着它们具有相同的函数集,但可能以不同的方式实现它们
抽象类本身并不定义实现。在程序中传递(指向的指针或引用)抽象类只传递一个“封闭包”,您可以与之交互(例如抖动)。但您隐藏了包内的内容,包括接口的实现方式(例如抖动时发生的情况)
也就是说,抽象类只是将抽象提高了一个级别。类描述对象具有的属性和行为,而抽象类只描述您可以对对象执行的操作。只有实际的实现定义了行为
尽管如此,一个重要的事实是您不能创建抽象类的实例
在设计一个软件时,抽象类/接口是一种非常重要的抽象方法。当软件的某个部分想要与它不知道的东西进行交互时,您可以编写一个接口来描述这样一个对象必须提供的功能,而不必指定实际的类型。这使得可以轻松地传递不同类型的对象。使用指向此类接口/抽象类的指针/引用的函数可以在不知道其实际类型的情况下与对象交互。下面是一个示例:假设您的程序需要计算不同形状的面积
class shape{
public:
virtual double area() = 0;
};
class triangle:public shape{
public:
triangle(double base, double height) : b(base), h(height) {}
double area(){ return 0.5 * b * h; }
private:
double b;
double h;
};
class circle:public shape{
public:
circle(double radius) : r(radius) {}
double area(){ return M_PI * r * r; }
private:
double r;
};
int main{
std::vector<shape*> shapes;
//add whatever shapes you want here
shapes.push_back( new triangle(4, 5) );
shapes.push_back( new circle(3) );
double dTotal = 0.0;
std::vector<shape*>::iterator i;
for (i = shapes.begin(); i != shapes.end(); i++)
{
dTotal += (*i)->area();
delete *i;
}
cout << dTotal;
return 0;
}
类形状{
公众:
虚拟双区()=0;
};
类三角形:公共形状{
公众:
三角形(双基,双高):b(基),h(高){}
双区域(){返回0.5*b*h;}
私人:
双b;
双h;
};
班级圈子:公共形态{
公众:
圆(双半径):r(半径){}
双区域(){return M_PI*r*r;}
私人:
双r;
};
int main{
向量形状;
//在这里添加您想要的任何形状
形状。推回(新三角形(4,5));
形状。推回(新圆圈(3));
双D总=0.0;
std::vector::迭代器i;
对于(i=shapes.begin();i!=shapes.end();i++)
{
dTotal+=(*i)->area();
删除*i;
}
cout在不希望创建类的对象的情况下,抽象类也很有用
想想这个,
/* Abstract Class Animal */
class Animal
{
public:
virtual void eat() = 0;
virtual void walk() = 0;
};
class Dog:public Animal
{
public:
void walk() { std::cout<<"\nWalk with Paws"; }
void eat() { std::cout<<"\nEat meat"; }
};
class Horse:public Animal
{
public:
void walk() { std::cout<<"\nWalk with Hooves"; }
void eat() { std::cout<<"\nEat Grass"; }
};
int main()
{
Dog d;
Horse h;
d.eat();
d.walk();
h.eat();
h.walk();
return 0;
}
/*抽象类动物*/
类动物
{
公众:
虚空eat()=0;
虚空行走()=0;
};
犬类:公共动物
{
公众:
void walk(){std::coutSteve Jessop已经指出了为什么需要抽象类和虚拟函数。
您可以强制使用vtable来实现动态调度
抽象基类声明派生类的公共特性。
虚函数确保在编译时无法确定对象的类型时调用正确的函数
在下面的示例中,类其他
在编译时不知道提供了类形状
的哪个派生。
唯一已知的是:每个shape
派生将为center
方法提供一个实现,因为它是纯virtual
(否则程序不会编译和链接)
这足以提供功能。
程序将在运行时确定shPtr
的类型,并调用正确的center()
完全正确(表示调用了正确的中心函数)
-编辑
/* Abstract Class Animal */
class Animal
{
public:
virtual void eat() = 0;
virtual void walk() = 0;
};
class Dog:public Animal
{
public:
void walk() { std::cout<<"\nWalk with Paws"; }
void eat() { std::cout<<"\nEat meat"; }
};
class Horse:public Animal
{
public:
void walk() { std::cout<<"\nWalk with Hooves"; }
void eat() { std::cout<<"\nEat Grass"; }
};
int main()
{
Dog d;
Horse h;
d.eat();
d.walk();
h.eat();
h.walk();
return 0;
}
#include <string>
#include <iostream>
using namespace std;
class v2d
{
public:
double x, y;
v2d (void) : x(0.0), y(0.0) { }
v2d (double const a, double const b) : x(a), y(b) { }
};
class shape
{
public:
string name;
shape (void) : name() { }
shape (string const n) : name(n) { }
virtual v2d center (void) const = 0;
};
class circle : public shape
{
private:
v2d center_point;
double radius;
public:
circle (void) : shape("Circle"), center_point(), radius(0.0) { }
circle (v2d const cp, double const r) : shape("Circle"), center_point(cp), radius(r) { }
v2d center (void) const { return center_point; }
};
class square : public shape
{
private:
v2d lowright;
double sidelength;
public:
square (void) : shape("Square"), lowright(), sidelength(0.0) { }
square (v2d const tl, double const sl) : shape("Square"), lowright(tl), sidelength(sl) { }
v2d center (void) const
{
double const halflen = sidelength/2.0;
return v2d(lowright.x+halflen, lowright.y+halflen);
}
};
class other
{
private:
shape *shPtr;
public:
other (void) : shPtr(NULL) { }
other (shape *sh_ptr) : shPtr(sh_ptr) { }
void doSomething (void)
{
cout << "Center of this Shape, which is a " << shPtr->name << " is: "<< shPtr->center().x << ", " << shPtr->center().y << endl;
}
};
int main (void)
{
v2d sq_c(1.0, 2.0), circ_c(4.0, 4.0);
square square_obj(sq_c, 5.0);
circle circle_obj(circ_c, 2.0);
other other1 (&square_obj), other2(&circle_obj);
cout << fixed << setprecision(2);
other1.doSomething();
other2.doSomething();
return 0;
}
Center of this Shape, which is a Square is: 3.50, 4.50
Center of this Shape, which is a Circle is: 4.00, 4.00
#include <string>
#include <iostream>
#include <vector>
using namespace std;
class Animal
{
public:
virtual string food() = 0;
virtual string name() = 0;
void eat() { cout << "A " << name() << " is eating " << food() << endl; }
};
class Dog:public Animal
{
public:
string name() { return "Dog"; }
string food() { return "Meat"; }
};
class Horse:public Animal
{
public:
string name() { return "Horse"; }
string food() { return "Gras"; }
};
void feed_all_animals (vector<Animal*> animals)
{
for (size_t i=0; i<animals.size(); ++i)
{
cout << "Feeding animal " << i+1 << " (a " << animals[i]->name() << ") with " << animals[i]->food() << endl;
animals[i]->eat();
}
}
int main (void)
{
vector<Animal*> animals;
// We have a zoo with three dogs and two horses
Dog dog1, dog2, dog3;
Horse horse1, horse2;
animals.push_back((Animal*)&dog1);
animals.push_back((Animal*)&dog2);
animals.push_back((Animal*)&dog3);
animals.push_back((Animal*)&horse1);
animals.push_back((Animal*)&horse2);
// now we let the user add another animal
int ani(0);
cout << "Do you want to add a Horse [1] or a Dog [0]: ";
cin >> ani;
switch (ani)
{
case 1: animals.push_back((Animal*)new Horse); break;
default: animals.push_back((Animal*)new Dog); break;
}
// so they don't starve
feed_all_animals(animals);
delete animals[animals.size()-1];
animals.clear();
return 0;
}