とりあえず以下のように必要なclassを定義します。

// listener
class ZoomVideoSDKDelegate : public IZoomVideoSDKDelegate {
public:
  virtual void onSessionJoin() {
    std::cout << "onSessionJoin" << std::endl;
  }
  // 長いので割愛
  ...
};

// 仮想スピーカー
class ZoomVideoSDKVirtualAudioSpeaker : public IZoomVideoSDKVirtualAudioSpeaker {
public:
  virtual void onVirtualSpeakerMixedAudioReceived(AudioRawData* data_) {}
  virtual void onVirtualSpeakerOneWayAudioReceived(AudioRawData* data_, IZoomVideoSDKUser* pUser) {}
  virtual void onVirtualSpeakerSharedAudioReceived (AudioRawData *data_) {}
};

// 仮想マイク
class ZoomVideoSDKVirtualAudioMic : public IZoomVideoSDKVirtualAudioMic {
public:
  virtual void onMicInitialize(IZoomVideoSDKAudioSender* rawdata_sender) {}
  virtual void onMicStartSend() {}
  virtual void onMicStopSend() {}
  virtual void onMicUninitialized() {}
};

次にjoin session周りの実装をします。
sessionのパスワードは設定しないものとします。

void joinVideoSession(std::string &sessionName, std::string &sessionToken, std::string &userName) {
    IZoomVideoSDK * video_sdk_obj = CreateZoomVideoSDKObj();
    ZoomVideoSDKInitParams init_params;
    init_params.domain = "https://go.zoom.us";
    init_params.enableLog = true;
    init_params.logFilePrefix = "適当なprefix";
    init_params.videoRawDataMemoryMode = ZoomVideoSDKRawDataMemoryModeHeap;
    init_params.shareRawDataMemoryMode = ZoomVideoSDKRawDataMemoryModeHeap;
    init_params.audioRawDataMemoryMode = ZoomVideoSDKRawDataMemoryModeHeap;
    init_params.enableIndirectRawdata = false;
    ZoomVideoSDKErrors err = video_sdk_obj -> initialize(init_params);
    if (err != ZoomVideoSDKErrors_Success) {
        printf("initialize failed, error code: %d\n", err);
        return;
    }

    IZoomVideoSDKDelegate * listener = new ZoomVideoSDKDelegate();
    video_sdk_obj -> addListener(dynamic_cast < IZoomVideoSDKDelegate * > (listener));

    ZoomVideoSDKSessionContext session_context;
    session_context.sessionName = sessionName.c_str();
    session_context.token = sessionToken.c_str();
    session_context.userName = userName.c_str();

    // マイク、カメラのon/offは環境によっていじってください
    session_context.videoOption.localVideoOn = false;
    session_context.audioOption.mute = true;

    session_context.virtualAudioSpeaker = new ZoomVideoSDKVirtualAudioSpeaker();
    session_context.virtualAudioMic = new ZoomVideoSDKVirtualAudioMic();
    session_context.audioOption.connect = true;

    video_sdk_obj -> joinSession(session_context);
}

joinVideoSessionを呼び出せばそのままsessionに参加できるものと思っていましたができませんでした。
最初次のような実装をしました。
無限ループで止めてますがcallbackはされるんじゃない?と思ってましたがされませんでした。

void main(int argc, char** argv) {
    std::string session_name, session_token, user_name;
    session_name = "session name";
    session_token = "jwt token";
    user_name = "適当な名前";

    joinVideoSession(session_name, session_token, user_name);

    while(true);
}

こちら の フォーラムで同じような問題に遭遇している人がいました。
例で上がっている実装を見た結果GLibを使ってg_main_loopを作って待ち受けると良いようです。

gboolean timeout_callback(gpointer data) {
    return TRUE;
}

void main(int argc, char** argv) {
    std::string session_name, session_token, user_name;
    session_name = "session name";
    session_token = "jwt token";
    user_name = "適当な名前";

    joinVideoSession(session_name, session_token, user_name);

    GMainLoop * loop = g_main_loop_new(NULL, FALSE);
    g_timeout_add(100, timeout_callback, NULL);
    g_main_loop_run(loop);
}

zoom video sdk for Linuxの実装例があまりなくて辛いですね。