用C++设计一个三角形类

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了用C++设计一个三角形类相关的知识,希望对你有一定的参考价值。

此三角形类为Triangle,包含三角形三条边长的私有数据成员,另有一个重载运算符“+”,以实现求两个三角形对象的面积之和。其中,在此类中设计一个友元函数operater+(Triangle t1,Triangle t2),它重载运算符“+”,返回t1和t2两个三角形的面积之和

写了个简单的类,请参考一下:#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<math.h>
class Triangle
public :
double area;//面积
friend double operator+(Triangle & ,Triangle &);//用友元函数重载运算符+
Triangle(int a,int b,int c)
double p;
side1=a;
side2=b;
side1=c;
if( (a+b<=c) ||(a+c<=b)||(b+c<=a))
printf("a,b,c can't buildup a triangle\n");
assert(0);

p=((double)(a+b+c))/2;
area=sqrt(p*(p-a)*(p-b)*(p-c));//海伦公式
printf("area=%lf\n",area);

private:
int side1;
int side2;
int side3;
;double operator+(Triangle &t1, Triangle &t2)
return t1.area+ t2.area;
void main()
double areaAdd;
Triangle t1(3,4,5);
Triangle t2(3,4,5);
areaAdd=t1+t2;
printf("面积之和:%lf\n",areaAdd);
//getchar();//test
参考技术A 文件1:tringle.h 代码:#ifndef _TRINGLE_H_
#define _TRINGLE_H_class CTringle

public:
//公共函数
CTringle();
CTringle(double da,double db,double dc);
double getLenth();
double getArea();
friend double operator+ (CTringle ca,CTringle cb);private:
double a;
double b;
double c;
double lenth;
double area;; #endif 文件2. tringle.cpp 代码:#include <iostream>
#include "tringle.h"
#include <math.h>
#include <iostream>
using namespace std;
CTringle::CTringle()

a = b = c =0;

CTringle::CTringle(double da,double db,double dc)

if ( da+db<dc || db+dc<da || da+dc<db)

cout<<"不能构成三角形"<<endl;
return ;

a = da;
b = db;
c = dc;

double CTringle::getArea()

area = sqrt(lenth*(lenth-a)*(lenth-b)*(lenth-c));
return area;

double CTringle::getLenth()

lenth = a+b+c;
return lenth;
double operator+ (CTringle ca,CTringle cb)

return ca.area+cb.area;

3.文件3 主函数:#include <iostream>
#include "tringle.h"
#include <string>
using namespace std;void main(int argc,char* argv[])

CTringle a(12,90,80);
CTringle b(20,43,52); cout<<a.getArea()<<endl;
cout<<b.getArea()<<endl;
cout<<a+b<<endl;

C++ 特殊类的设计

1. 请设计一个类,只能在堆上创建对象

实现方式:

1.将类的构造函数私有(不能直接定义对象了)

2.提供一个静态的成员函数,在该静态成员函数中完成堆对象的创建(因为,构造函数私有,在外面不能调动,就需要成员函数去调动,而成员函数需要成员调动,但是不能创建成员,因此用一个静态函数去调用构造函数)

3.创建出来的对象虽然是在堆上的,但是由于拷贝函数的存在,可能会拷贝到栈上,因此将拷贝构造声明为私有的且不实现,或者直接删除掉

只声明不实现的原因是,防止内部进行拷贝。私有的原因是,防止外部进行定义
当然,最简洁的方法是直接删除掉

class HeapOnly
{
public:
	static HeapOnly *GetObject()
	{
		return new HeapOnly;
	}

private :
	HeapOnly()
	{}
	//HeapOnly(const HeapOnly &hp)//只声明,不实现
	HeapOnly(const HeapOnly &hp) = delete;//直接删除
};


void test()
{
	HeapOnly *hp = HeapOnly::GetObjectA();
	HeapOnly copy(*hp);//可能会进行拷贝,所以禁止掉拷贝构造
}

2.请设计一个类,只能在栈上创建对象

方法1:

1.将构造函数私有化,然后设计静态方法创建对象返回即可

2.由于构造函数私有,因此只能通过提供的进口进行对象的创建,杜绝了用new创建对象的可能

class StackOnly
{
public:
	static StackOnly GetObject()
	{
		return StackOnly();//构造一个匿名对象,拷贝返回即可
	}

private:
	StackOnly()
	{}
};

void test()
{
	StackOnly sk = StackOnly::GetObjectA();
}

方法2:

屏蔽new,因为new在底层调用void * operator new(size_t size)函数,只需将该函数屏蔽掉即可

class StackOnly
{
public:

	StackOnly()
	{}
	//operator new是库函数,和malloc用法是一样的
	void* operator new(size_t size) = delete;
};

void test()
{
	StackOnly sk;
}

3.请设计一个类,不能被拷贝

拷贝只会放生在两个场景中:拷贝构造函数以及赋值运算符重载,因此想要让一个类禁止拷贝,只需让该类不能调用拷贝构造函数以及赋值运算符重载即可

方法1(C++ 98):

将拷贝构造函数与赋值运算符重载只声明不定义,并且将其访问权限设置为私有即可

class NoCopy
{
public:
	NoCopy()
	{}
private:
	NoCopy(const NoCopy& nc);
	NoCopy& operator = (NoCopy& nc);
};

方法2(C++ 11):

直接删除掉

class NoCopy
{
public:
	NoCopy()
	{}

	NoCopy(const NoCopy& nc) = delete;
	NoCopy& operator = (NoCopy& nc) = delete;
};

4.请设计一个类,不能被继承

方法1(C++ 98):

构造函数私有化,派生类中调不到基类的构造函数(基类的成员,必须调用基类的构造函数进行初始化),则无法继承

class parent
{
private:
	parent()
	{};
};

class child:public parent
{
	child()
	{}
};

方法2(C++ 11):
final关键字,final修饰类,表示该类不能被继承

class parent final //final修饰,不能被继承
{
public:
	parent()
	{};
};

class child:public parent
{
	child()
	{}
};

5. 请设计一个类,只能创建一个对象(单例模式)

单例模式:
一个类只能创建一个对象,即单例模式,该模式可以保证系统中该类只有一个实例,并提供一个访问它的全局访问点,该实例被所有程序模块共享。比如在某个服务器程序中,该服务器的配置信息存放在一个文件中,这些配置数据由一个单例对象统一读取,然后服务进程中的其他对象再通过这个单例对象获取这些配置信息,这种方式简化了在复杂环境下的配置管理。

单例模式有两种实现模式:

饿汉模式:
就是说不管你将来用不用,程序启动时就创建一个唯一的实例对象

如果这个单例对象在多线程高并发环境下频繁使用,性能要求较高,那么显然使用饿汉模式来避免资源竞争,提高响应速度更好。

class singleton
{
public:

	//不能直接调用构造,因为直接调用构造返回时,需要进行拷贝
	static singleton* getInstance()//返指针,都是同一个对象
	{
		return &_single;//这里是只读的,因此不用进行加锁处理
	}
private:

	singleton(){};//构造函数私有,避免构造出来多个对象
	
	//拷贝、赋值需要禁掉
	singleton(const singleton&s) = delete;
	singleton& operator=(const singleton&s) = delete;

	static singleton _single;//给一个静态的对象,在编译时就已经初始化好了
};

//静态成员初始化
singleton singleton::_single;

特点:

构造函数私有
提供一个静态的方法返回单例
声明一个静态的单例成员
拷贝构造和赋值声明为delete函数

优缺点:

优点:实现简单、多线程场景下效率高
缺点:程序启动慢、多个单例的初始化顺序是无法控制的

懒汉模式:

如果单例对象构造十分耗时或者占用很多资源,比如加载插件啊, 初始化网络连接啊,读取文件啊等等,而有可能该对象程序运行时不会用到,那么也要在程序一开始就进行初始化,就会导致程序启动时非常的缓慢。 所以这种情况使用懒汉模式(延迟加载)更好。

class singleton2
{
public:

	static singleton2 *getInstance()//返回指针
	{
		_mtx.lock();//防止临界资源不安全,进行加锁
		//初始化一次
		if (_ptr == nullptr)
		{
			_ptr = new singleton2;
		}
		_mtx.unlock();

		return _ptr;
	}

	// 实现一个内嵌内部类垃圾回收类
	class CGarbo //程序结束了,资源自然会还给系统,可写可不可
	{
	public:
		~CGarbo()
		{
			if (_ptr)
				delete _ptr;
		}
	};

private:

	singleton2()
	{};

	//拷贝、赋值需要禁掉
	singleton2(const singleton2&s) = delete;
	singleton2& operator=(const singleton2&s) = delete;

	static singleton2* _ptr;
	static mutex _mtx;
	
	// 声明一个静态成员变量,程序结束时,系统会自动调用它的析构函数从而释放单例对象
	static CGarbo _cg;
};

singleton2* singleton2::_ptr = nullptr;//初始化为空
mutex singleton2::_mtx;//初始化锁
singleton2::CGarbo singleton2::_cg;//初始化	

特点:

构造函数私有
提供一个静态的方法返回单例,第一次调用创建对象,后续调用直接返回
声明一个静态的单例成员指针,指针初始化为空
拷贝构造和赋值声明为delete函数
保证线程安全(修改指针),双检查提高效率

优缺点:

优点:延迟加载,启动快。可以指定多个单例对象的初始化顺序
缺点:实现复杂一点

测试:是否只有一个对象

void test()
{
	singleton *s = singleton::getInstance();
	singleton2 *s2 = singleton2::getInstance();
	
	cout << "s:" << s << " " << "s2:" << s2 << endl;
	cout << "-------" << endl;

	for (int i = 0; i < 10; i++)
	{
		cout << "s:"<<singleton::getInstance() <<" "<<"s2:" <<singleton2::getInstance() << endl;
	}
}

image-20210619163153626

以上是关于用C++设计一个三角形类的主要内容,如果未能解决你的问题,请参考以下文章

第八次作业

c++定义多边形类,派生出矩形类,和三角形类,编写主函数求面积。

c++杨辉三角

设计满足约束的三角形类

C++编程练习:抽象类——编写一个程序,计算三角形正方形的面积,抽象出一个基类base。

OpenGL不在C++中绘制三角形