2010-08-20 2 views
1

Является ли следующий код законным в C++. Доступ к общедоступному методу участника класса друзей? Я знаю, что это звучит запутанно, и лучший способ показать это в коде. Мне было интересно, верен ли TestClassC :: Method() в коде ниже?C++ Доступ к общедоступному методу друзей class-> member->?

Я скомпилировал (g ++), но он работает, однако я столкнулся с ситуацией, когда он вызывает ошибку сегментации на других машинах/дистрибутивах в TestClassC :: Method(). Что заставляет меня задаться вопросом, если this-> classA_Ptr-> classB.Method(); является законным в C++.

#include <iostream> 

using namespace std; 

class TestClassB 
{ 
    public: 
     TestClassB(void){}; 
     ~TestClassB(void){}; 
     void Method(void){ 
     cout << "Hello Again" << endl; 
     } 
}; 


class TestClassC; //Forward Declaration 
class TestClassA 
{ 
    friend class TestClassC; 

    public: 
     TestClassA(void){}; 
     ~TestClassA(void){}; 

    private: 
     TestClassB classB; 
}; 


class TestClassC 
{ 
    public: 
     TestClassC(TestClassA* a_Ptr){ 
     this->classA_Ptr = a_Ptr; 
     } 
     ~TestClassC(void){}; 

     void Method(void){ 
     //Is this Valid/Legal ??? 
     this->classA_Ptr->classB.Method(); 
     } 

    private: 
     TestClassA* classA_Ptr; 
}; 



int main() 
{ 
    cout << "Hello world!" << endl; 

    TestClassA testClassA; 
    TestClassC classC(&testClassA); 

    classC.Method(); 

    return 0; 
} 
+0

Кажется прекрасным для меня - я не понимаю, почему это может быть segfault. Хорошо работает и на моей платформе (MacOSX 10.5, Intel CPU). –

+0

Он работает для меня в Xcode, и я уверен, что gcc. Просто говорю'. – 2010-08-20 03:10:49

+0

Проверьте состояние члена 'classA_Ptr', когда вы получаете seg-fault. То, что у вас есть, - это действительно действующий код. Возможно, что указатель 'class A' недействителен извне и является висячей ссылкой при попытке получить к нему доступ. – dirkgently

ответ

4

Модификаторы общедоступного/частного/защищенного доступа применяются во время компиляции, а не во время выполнения. SEGFAULT - это ошибка времени выполнения, а не ошибка времени компиляции. Итак, в будущем, если вы получите SEGFAULT, вы можете быть уверены, что это не связано с уровнем доступа. Похоже, что ваша путаница основана на том, применяются ли модификаторы доступа напрямую, косвенно, транзитивно и т. Д. Модификаторы доступа работают самым простым и прямым способом: они применяются только непосредственно к объявленным функциям или переменным в этом классе и контролировать доступ через данный класс к этим элементам. Как только у вас есть доступ к такому элементу, дальнейший доступ определяется исключительно собственными модификаторами доступа этого элемента.

SEGFAULT обычно указывает на незаконный доступ к памяти. Если вы испытываете SEGFAULTS, посмотрите, где вы указатели разыменования (всякий раз, когда у вас есть * X или X-> Y). Общие причины SEGFAULTS включают разыменование NULL, доступ к каждому элементу по отдельности и использование объекта через указатель, в котором объект, о котором идет речь, уже был удален путем выхода из области видимости.

1

Вызов общих методов любого класса является действительным/законно, пока класс однозначно доступен, и у нас есть действительное выражение объекта для доступа к нему. Фактически именно поэтому он был обнародован в первую очередь. Ваш код выглядит для меня хорошим.

2

Да. Спецификация friend предоставляет TestClassC доступ к любым защищенным или закрытым членам TestClassA. Таким образом, это означает, что он получает доступ к члену класса B. После этого нормальные правила применяются к тому, что TestClassC может сделать с этим членом. И поскольку метод() является общедоступным, TestClassC разрешает его вызывать, как если бы он получил экземпляр TestClassB любым другим способом.


Что касается вины SEG:

Public/защищенный/частный/друга все время компиляции ограничений. Они не должны влиять на работу кода во время выполнения.

Это точный код, который неисправен seg? Или это что-то похожее в концепции? Если это не тот же самый код, то вы подтвердили, что все указатели действительно действительны в проблемном коде?

+0

Код что-то похожее, но концепция такая же. Я просто хотел убедиться, что это действительно, потому что я был не уверен. Я думаю, что у Майкла это правильно. Из-за незаконного адреса памяти должно быть что-то.Раньше я делаю вызов DMA, он должен что-то влиять на что-то вскоре, и просто происходит с segfaults в строке, на которую я тоже ссылался. Поскольку код работает на встроенной плате, у меня нет доступа к хорошему отладчику, например, gdb, и я могу полагаться только на использование целой группы cout, чтобы сузить код нарушения. –

Смежные вопросы