Как решить, что «IServiceProvider» неоднозначен при использовании «wininet» и «windows.h»?

#c #visual-studio #visual-studio-2019

#c #visual-studio #visual-studio-2019

Вопрос:

Я пытаюсь проверить, существует ли подключение к Интернету или нет, используя InternetCheckConnection функцию wininet .

Вот мой CheckerClass: который обрабатывает процесс проверки.

 #pragma once
#include <Windows.h>
#include <wininet.h>
#pragma comment(lib,"wininet.lib")
#include <String>

public ref class CheckerClass
{
public:
    static std::string hasInternet() {
        bool bConnect = InternetCheckConnection(L"https://www.google.com", FLAG_ICC_FORCE_CONNECTION, 0);
        if (bConnect){
            return "Has Internet!";
        }else{
            return "No Internet!";
        }
    }
};
 

Но я получаю следующую ошибку и не могу ее решить.

 Error (active)  E1986   an ordinary pointer to a C  /CLI ref class or interface class is not allowed
Error (active)  E0266   "IServiceProvider" is ambiguous
Error   C3699   '*': cannot use this indirection on type 'IServiceProvider' 
 

После поиска я обнаружил, что это может быть связано с использованием using namespace System , но у меня этого нет в вышеупомянутом классе.

Тем не менее, у меня есть следующее из основного класса, где я использую вышеупомянутый класс.

 #pragma once
#include<string>
#include "CheckerClass.h"
namespace CppCLRWinformsProjekt {

    using namespace System;
    using namespace System::ComponentModel;
    using namespace System::Collections;
    using namespace System::Windows::Forms;
    using namespace System::Data;
    using namespace System::Drawing;
    using std::string;

    public ref class Form1 : public System::Windows::Forms::Form
    {
    public:

        CheckerClass checkerClass;
        
        Form1(void)
        {
            InitializeComponent();
            string result = checkerClass.hasInternet();
            this->label_output->Text = gcnew System::String(result.c_str());
        }

    .....
 

Кто-нибудь может объяснить, что происходит и как я могу решить вышеуказанную проблему?

Комментарии:

1. Это файлы .h, вы еще не нашли файл .cpp, который #включает их. И содержит using namespace System, что приводит к искажению объявлений Windows.h. Одна очевидная ошибка, о которой вы должны получить диагностику, — это переменная checkerClass, которая должна быть объявлена как CheckerClass ^ .

2. @HansPassant — Я думаю, у меня есть проблемы с классом.

Ответ №1:

Какой CheckerClass у вас есть? Классы обычно разделяются на два файла. Что означает, что вы должны иметь CheckerClass.h и CheckerClass.cpp . Где этот приведенный выше код из этих двух файлов?

В любом случае, вот пример рабочего класса на основе вашего кода.

В вашем CheckerClass.h файле вы должны иметь;

 #include <string>
#ifndef CHECKER_CLASS_H
#define CHECKER_CLASS_H
using std::string;
class CheckerClass {

private:
    //declare private variables here, if you need one.
public:

    CheckerClass(); 
    
    string hasInternet(); //The function
};
#endif
 

Затем реализация класса переходит в CheckerClass.cpp файл;

 #include "CheckerClass.h"
#include "string"
#include "windows.h"
#include "wininet.h"
#pragma comment(lib,"wininet.lib")

CheckerClass::CheckerClass() {
    //initialize variable here if needed.
}

std::string CheckerClass::hasInternet() {
    bool bConnect = InternetCheckConnection(L"https://www.google.com", FLAG_ICC_FORCE_CONNECTION, 0);
    if (bConnect) {
        return "has Internet";
    }
    else {
        return "no internet";
    }
}
 

Тогда теперь вы можете получить результат с помощью своего кода;

 string result = checkerClass.hasInternet();
this->label_output->Text = gcnew System::String(result.c_str());
 

Это позволит избежать конфликтов и ошибок, с которыми вы сталкиваетесь.

Комментарии:

1. Итак, в основном конфликты происходили из-за того, что я неправильно инициализировал свой класс. Я немного запутался с h file и cpp file. Я думал, что концепция создания класса на C и Java одинакова. Спасибо!

Ответ №2:

Это потому using namespace System; , что конфликтует с именем в Windows.h ,

Windows.h введен servprov.h косвенный. И servprov.h имеет следующее определение: typedef interface IServiceProvider IServiceProvider; среди них IServiceProvider конфликты с IServiceProvider в пространстве имен System, вызывающие неопределенность.

Решение состоит в том, чтобы использовать полное имя вместо системного пространства имен, например System::IServiceProvider .

Комментарии:

1. Можете ли вы рассказать мне об этом подробнее? Где я должен это сделать? Потому что я попытался удалить пространство имен, связанное System с основным классом, и все равно получил ту же проблему. Я пытался использовать System::IServiceProvider on CheckerClass и все еще получал ту же проблему.

2.Вы могли бы попытаться закомментировать все using namespace System; при использовании IServiceProvider , используйте System::IServiceProvider вместо этого. Есть и другая возможность. Посмотрите в ваших включенных файлах, включены ли два параметра пространства имен в вложенном файле. Например, using namespace System; using namespace System::IO; конфликт был вызван дублированием настроек в одном из включенных файлов.

3. Итак, в основном конфликты происходили из-за того, что я неправильно инициализировал свой класс. Я немного запутался с h file и cpp file. Я думал, что концепция создания класса на C и Java одинакова. Спасибо!