экстерн C не может использоваться на уровне класса?

следующий код работал для меня

@interface TopAlignedCollectionViewFlowLayout : UICollectionViewFlowLayout

- (void)alignToTopForSameLineElements:(NSArray *)sameLineElements;

@end

@implementation TopAlignedCollectionViewFlowLayout

- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect;
{
    NSArray *attrs = [super layoutAttributesForElementsInRect:rect];
    CGFloat baseline = -2;
    NSMutableArray *sameLineElements = [NSMutableArray array];
    for (UICollectionViewLayoutAttributes *element in attrs) {
        if (element.representedElementCategory == UICollectionElementCategoryCell) {
            CGRect frame = element.frame;
            CGFloat centerY = CGRectGetMidY(frame);
            if (ABS(centerY - baseline) > 1) {
                baseline = centerY;
                [self alignToTopForSameLineElements:sameLineElements];
                [sameLineElements removeAllObjects];
            }
            [sameLineElements addObject:element];
        }
    }
    [self alignToTopForSameLineElements:sameLineElements];//align one more time for the last line
    return attrs;
}

- (void)alignToTopForSameLineElements:(NSArray *)sameLineElements
{
    if (sameLineElements.count == 0) {
        return;
    }
    NSArray *sorted = [sameLineElements sortedArrayUsingComparator:^NSComparisonResult(UICollectionViewLayoutAttributes *obj1, UICollectionViewLayoutAttributes *obj2) {
        CGFloat height1 = obj1.frame.size.height;
        CGFloat height2 = obj2.frame.size.height;
        CGFloat delta = height1 - height2;
        return delta == 0. ? NSOrderedSame : ABS(delta)/delta;
    }];
    UICollectionViewLayoutAttributes *tallest = [sorted lastObject];
    [sameLineElements enumerateObjectsUsingBlock:^(UICollectionViewLayoutAttributes *obj, NSUInteger idx, BOOL *stop) {
        obj.frame = CGRectOffset(obj.frame, 0, tallest.frame.origin.y - obj.frame.origin.y);
    }];
}

@end
10
задан George2 22 June 2009 в 03:11
поделиться

5 ответов

C99 имеет отличную инициализацию структуры любого порядка. Конечно, вы не можете применить его к шаблону C ++. Вы также не можете применить его к методам класса (потому что метод класса должен знать, для какого объекта он был вызван, а связь в стиле C не имеет никакого способа передать эту информацию функции).

Это возможно применить extern «C» к функциям, которые существуют в пространстве имен, но информация о пространстве имен просто исчезнет при использовании через C.


Обновление

Если у вас уже есть класс (мы будем использовать класс POD для простоты), и вы хотите, чтобы его можно было использовать из C, вам нужно применить extern «C» к функции, вызываемой в C К сожалению, это становится некрасивым даже в простых случаях:

// in the header file
#ifdef __cplusplus
namespace X {
#endif
    struct A
    {
        int x;
#ifdef __cplusplus
        A() : x(5) { }
        int foo()
        {
             return x += 5;
        }
#endif
    };
#ifdef __cplusplus
    extern "C" {
#endif
        int A_foo(struct A a);
        struct A A_create();
#ifdef __cplusplus
    }
}
#endif


// in the .cc file
#include "try.h"

namespace X {
    extern "C" {
        int A_foo(A* a)
        {
            return a.foo();
        }

        A A_create()
        {
            return A();
        }
    }
}

// in the .c file
#include <stdio.h>
#include "try.h"

int main()
{
    struct A a = A_create();
    printf("%d", A_foo(a));
}

Используя gcc, вы бы скомпилировали это следующим образом:

  • файл C ++: g ++ try.cc -c -o try.o
  • файл C:
  • Когда структура выпадает из области видимости в коде C, деструктор C ++ не вызывается (некоторые компиляторы могут обещать это сделать, но это не стандартно). Если вам нужно очистить эти объекты, вам нужно будет вызвать функцию extern «C», которая вызывает деструктор.

Чтобы вызвать деструктор явно:

extern "C" void A_destroy(struct A a)
{
    a.~A();
}
5
ответ дан 3 December 2019 в 15:36
поделиться

extern "c" использует связывание в стиле c; то есть необработанное имя функции - это то, что отображается из библиотеки. Поскольку это просто необработанное имя функции, ни одна из функций C ++ не будет работать с ней, включая методы или внешние данные-члены в пространствах имен, классах, структурах или объединениях.

Уточнение : Структуры и объединения находятся в C , но не имеют функций-членов, поэтому их функции-члены в C ++ нельзя экспортировать в стиле c (а определения структуры и объединения не нужно экспортировать, поскольку они уже находятся в заголовке)

5
ответ дан 3 December 2019 в 15:36
поделиться

Боюсь, что нет. Но если вы хотите передать объект C ++ в функции C, вы можете обратиться к этой ссылке: http://www.parashift.com/c++-faq-lite/mixing-c-and-cpp.html# faq-32.8

4
ответ дан 3 December 2019 в 15:36
поделиться

Ммм ... extern "C" принудительно устанавливает связь в стиле C. Его нельзя использовать с классами AFAIK.

2
ответ дан 3 December 2019 в 15:36
поделиться

Вы можете вроде как применить extern "C" к функции-члену с помощью очень запутанного (но полностью легального) хака:

extern "C" typedef int bar_t(int x);

struct foo {
     bar_t bar; // yes, this declares a nonstatic member function!
};

int foo::bar(int x) { return x; } // definition

Это возможно согласно ISO C++03 9.3[class.mfct]/9:

функция-член может быть объявлена (но не определена) с помощью typedef для типа функции. Результирующая функция-член имеет точно такой же тип, как если бы декларатор функции был представлен явно, см. 8.3.5.

Однако на самом деле это ничего не дает, так как в ISO C++03 7.5[dcl.link]/4:

Синхронизация языка Си игнорируется для имен членов класса и функции-члена тип функций члена класса.

12
ответ дан 3 December 2019 в 15:36
поделиться
Другие вопросы по тегам:

Похожие вопросы: