一个简单的基于C++的免main函数的主程序框架类

教家里娃儿学习C++语言时,为了讲解C++的封装、继承、多态性等,写了个简单的主程序框架类。应用程序只要从这个主程序框架类派生出子类,实现其run(...)方法,然后定义一个子类实例即可。

抽象应用程序类AbstractApplication类的代码如下:

// absapp.h
#ifndef __ABSAPP_H
#define __ABSAPP_H
/**
 * AbstractApplication 应用程序的抽象框架类。
 * 应用程序主类应该从此类派生,override其纯虚函数run,随后定义一个应用程序主类的全局对象实例即可。
 * 应用程序的project中应当包含与本类配套的main.cpp/h(用于控制台应用)或winmain.cpp/h(用于Windows GUI应用)。
 * 若要获得命令行参数,则应用程序还应#include "main.h"或#include "winmain.h"。
 */
class AbstractApplication
{
   public:
      AbstractApplication()   {  instance = this;  }
      virtual ~AbstractApplication()  {}

   public:
      static AbstractApplication *getInstance()  {  return instance;  }
      static int start(void *params);

   protected:
      virtual int run(void *params) = 0;

      static AbstractApplication *instance;
};

#endif /* __ABSAPP_H */

// absapp.cpp
#include "absapp.h"

AbstractApplication *AbstractApplication::instance;

int AbstractApplication::start(void *params)
{
   instance->run(params);

   return 0;
}

控制台程序的main()函数实现代码如下:

// main.h
#ifndef __MAIN_H
#define __MAIN_H

typedef struct __tagMainArgs
{
   int argc;
   char **argv;
} MainArgs;

#endif /* __MAIN_H */


// main.cpp
#include "absapp.h"
#include "main.h"

int main(int argc, char *argv[])
{
   MainArgs args;
   args.argc = argc;
   args.argv = argv;
   return AbstractApplication::start(&args);
}

Windows GUI程序的WinMain函数实现代码如下:

// winmain.h
#ifndef __WINMAIN_H
#define __WINMAIN_H

#include <windows.h>

typedef struct __tagWinMainArgs
{
   HINSTANCE hInstance;
   HINSTANCE hPrevInstance;
   LPSTR lpCmdLine;
   int nCmdShow;
} WinMainArgs;

#endif /* __WINMAIN_H */


// winmain.cpp
#include "absapp.h"
#include "winmain.h"

int WINAPI WinMain(HINSTANCE hThisInstance, HINSTANCE hPrevInstance, LPSTR lpszArgument, int nCmdShow)
{
   WinMainArgs args;
   args.hInstance = hThisInstance;
   args.hPrevInstance = hPrevInstance;
   args.lpCmdLine = lpszArgument;
   args.nCmdShow = nCmdShow;
   return AbstractApplication::start(&args);
}

上述代码可以用编译器打包,做成静态链接的库文件,供应用程序使用。

测试代码如下:

// testCaseApp.cpp

#include <iostream>
#include <absapp.h>

using namespace std;

class TestCaseApp : public AbstractApplication
{
public:
   TestCaseApp()  {}
   virtual ~TestCaseApp()  {}

   virtual int run(void *params) override
   {
      cout << "Hello, no-main Application Framework." << endl;
      return 0;
   }

private:

};

TestCaseApp testCaseApp;

这个程序在运行时,运行环境会首先创建TestCaseApp类的全局实例testCaseApp对象。在创建这个对象实例时,AbstractApplication的构造函数首先被调用,会将静态成员AbstractApplication::instance初始化为this。由于这时是在创建testCaseApp对象,因此此时的this指针代表的是testCaseApp对象,因此AbstractApplication::instance也就指向了testCaseApp对象。当main()函数能够运行时,testCaseApp对象已经完成创建。随后main函数调用AbstractApplication::start(...),而AbstractApplication::start(...)调用了instance->run(params)。由于这时instance已经指向了testCaseApp,因此instance->run(...)调用的就是testCaseApp对象的run(...)成员函数。

从上述测试代码可以看出,在应用程序看来,这个程序是没有main函数的,只有一个全局对象。这个例子使用了C++的封装、继承、多态等特性解决了C++一直被人诟病的未能摆脱全局的main函数的毛病,其实就是把main藏起来了而已。但是,没有了全局函数,却多了个全局变量,其实也没好到哪儿。其实任何一种语言,总归会需要一个全局的入口点的。就连号称OO做得好的Java,同样也需要在主类中定义一个静态的main函数。过度追求“无全局数据”没啥意思。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值