为啥要使用接口?因为有多个电源,接口都相似的。再加型号上层很少改动(类型切换)或不用改。
 为啥要使用友元?友元函数的主要作用是允许外部函数或类访问被声明为友元的类的私有成员。
 如果不使用友元怎么做?最后回答。
 
1.C++定义dll接口
// The following ifdef block is the standard way of creating macros which make exporting 
// from a DLL simpler. All files within this DLL are compiled with the PSU_DLL_EXPORTS
// symbol defined on the command line. this symbol should not be defined on any project
// that uses this DLL. This way any other project whose source files include this file see 
// PSU_DLL_API functions as being imported from a DLL, whereas this DLL sees symbols
// defined with this macro as being exported.
#pragma once
#ifndef PSU_DLL_H
#define PSU_DLL_H
#ifdef PSU_DLL_EXPORTS
#	define PSU_DLL_API __declspec(dllexport)
#else
#	define PSU_DLL_API __declspec(dllimport)
#endif
#include <tchar.h>
#ifdef __cplusplus
extern "C" {
#endif
//
typedef enum
{
	PSU_UNKONW = -1,
	PSU_BEGIN = 0,
	PSU_Agilent_663xx = 0,
	PSU_Agilent_E3631A,
	PSU_GWINSTTEK_PPH1503D,
	PSU_END
} PSU_TYPE;
typedef enum
{
	PSU_OFF = 0,
	PSU_ON,
} PSU_ONOFF;
//
// PSU Interface
class CPSUInterface
{
	friend PSU_DLL_API CPSUInterface* PSUCreate(const char* pcPsuGpibAddr, PSU_TYPE ePsuType);
protected:
	CPSUInterface();
public:
	virtual ~CPSUInterface(void);
	virtual int PSU_Initialize(double Voltage_Limit, double Current_Limit) = 0;
	virtual int PSU_PowerOnOff(PSU_ONOFF OnOffState) = 0;
	virtual int PSU_Set_VoltCurr(double Target_Voltage, double Target_Current) = 0;
	virtual int PSU_Voltage_Measure(double *Voltage_Result, double *Current_Result) = 0;
	virtual int PSU_DeInitial() = 0;
};
// Can't construct directly, use this, delete the pointer if no longer use
PSU_DLL_API CPSUInterface* PSUCreate(const char* pcPsuGpibAddr, PSU_TYPE ePsuType);
#ifdef __cplusplus
}
#endif
#endif // #ifndef PSU_DLL_H
2.导出接口。导出友元函数。定义基类继承接口类,存放一些通用的变量值,如地址,message等。具体类继承基类。
// PSU_DLL.cpp : Defines the exported functions for the DLL application.
//
#include "stdafx.h"
#include "PSU_DLL.h"
#include "AG663XX.h"
#include "AG3631A.h"
#include "GW1503D.h"
CPSUInterface::CPSUInterface()
{
}
CPSUInterface::~CPSUInterface(void)
{
}
CPSUInterface* PSUCreate(const char* pcPsuGpibAddr, PSU_TYPE ePsuType)
{
	switch (ePsuType)
	{
	case PSU_Agilent_663xx:
		return new CAG663XX(pcPsuGpibAddr, ePsuType);
	case PSU_Agilent_E3631A:
		return new CAG3631A(pcPsuGpibAddr, ePsuType);
	case PSU_GWINSTTEK_PPH1503D:
		return new GW1503D(pcPsuGpibAddr, ePsuType);
	default:
		return NULL;
	}
}
#include "stdafx.h"
#include "PSUBasic.h"
CPSUBasic::CPSUBasic(const char* pcPsuGpibAddr,PSU_TYPE ePsuType )
{
	strcpy_s(m_cPsuGpibAddr, pcPsuGpibAddr);
	m_ePsuType = ePsuType;
	m_bPsuInitFlag = false;
	m_vsPsuHandle = NULL;
	memset(m_cErrorMSG, 0, sizeof(m_cErrorMSG));
}
CPSUBasic::~CPSUBasic(void)
{
}
void CPSUBasic::PSU_GetErrorMsg( char* pcErrorMSG, int iMsgSize)
{
	if (iMsgSize > 100)
		iMsgSize = 100;
	strcpy_s(pcErrorMSG, iMsgSize, m_cErrorMSG);
}
3.友元函数切换多态 返回句柄指针

4.句柄指针调用具体类

 
5.删除指针。

 
 

如果不使用友元函数,你可以通过提供公共的成员函数或访问器函数来实现对类的私有成员的访问。这可以帮助维持封装性,而无需将外部函数或类声明为友元。以下是一些方法:
-  公共成员函数:在类中提供公共成员函数,这些函数可以用于修改或访问私有成员。这是最常见的方式,遵循了封装的概念。 class MyClass { private: int privateData; public: int getPrivateData() { return privateData; } void setPrivateData(int value) { privateData = value; } };在这个示例中, getPrivateData和setPrivateData是用于获取和设置私有成员privateData的公共成员函数。
-  访问器函数:如果需要更细粒度的控制,你可以使用访问器函数,这些函数可以用于获取和设置私有成员,同时允许你添加额外的逻辑。 class MyClass { private: int privateData; public: int getPrivateData() { // 可以在这里添加额外的逻辑 return privateData; } void setPrivateData(int value) { // 可以在这里添加额外的逻辑 privateData = value; } };这种方法允许你在访问私有成员时执行自定义操作,例如范围检查或日志记录。 
使用公共成员函数或访问器函数的好处是,它们保持了封装性,同时提供了对私有成员的受控访问,而不需要使用友元函数。友元函数通常是在需要更特殊的访问权限或操作时使用的,但应谨慎使用以保持良好的封装性。



















